为防止广告,目前nocow只有登录用户能够创建新页面。如要创建页面请先登录/注册(新用户需要等待1个小时才能正常使用该功能)。

Sgu/126

来自NOCOW
< Sgu
跳转到: 导航, 搜索

[编辑] 数学解法

一个二进制的数学题,证明详见:http://damselfly.diandian.com/post/2011-10-25/6203890

#include <stdio.h>
using namespace std;
 
int a, b;
 
int gcd(int a, int b)
{
    int c;
    while (c = a % b)
          a = b, b = c;
    return b;
}
 
int main()
{
    scanf("%d %d", &a, &b);
    if (!a || !b) {
       printf("0");
       return 0;
    }
    int s = (a + b) / gcd(a, b), res = 0;
    while (!(s & 1)) 
    {
          s /= 2;
          res++;
    }
    if (s == 1) printf("%d", res);
       else     printf("-1");    
    return 0;
}
// From FingerSed

[编辑] 模拟解法

首先我们需要知道,求 A,B 的步数其实就等同于求 A/gcd(A,B),B/gcd(A,B) 的步数。

对于这个的证明很明显,每次移动的求一定是 gcd(A,B) 的倍数。

对于每次移动,令 A = A/gcd(A,B) ,B = B/gcd(A,B),讨论情况 :

(1) A,B都为偶数(不可能)

(2) A,B有一个为奇数 (无解,很明显吧,因为A+B都是奇数了)

(3) A,B都是奇数-> 假设A是较小的那一个,那么就可以变化为 A*2,B-A ,然后我们的新目标就变成了求解 A*2,B-A 的步数

结束条件 A=0 或 B=0

容易证明,上述步骤重复次数最多不超过 log(A+B)次

#include<iostream>
using namespace std;
int gcd(int a,int b)
{
	if(b!=0) return gcd(b,a%b);
	return a;
}
int A0,B0;
int solve(int A,int B)
{
	if(!A||!B) return 0;
	int t=gcd(A,B);
	A/=t;B/=t;
	if(!(A%2==1&&B%2==1)) return -1;
	if(A>B) swap(A,B);
	t=solve(A*2,B-A);
	return t==-1?-1:t+1;
}
int main()
{
	cin>>A0>>B0;
	cout<<solve(A0,B0);
	return 0;
}
个人工具