Last Denfence
Last Defence
Description
Given two integers A and B. Sequence S is defined as follow:
• S0 = A
• S1 = B
• Si = |Si−1 − Si−2| for i ≥ 2
Count the number of distinct numbers in S.
Input
The first line of the input gives the number of test cases, T. T test cases follow. T is about
100000.
Each test case consists of one line - two space-separated integers A, B. (0 ≤ A, B ≤ 10^18).
Output
For each test case, output one line containing “Case #x: y”, where x is the test case
number (starting from 1) and y is the number of distinct numbers in S.
Samples
Sample Input
2
7 4
3 5
Sample Output
Case #1: 6
Case #2: 5
题意:
这道题是先让你输入两个数A和B,设S0=A,S1=B,然后后面就是S2=S1-S0,SN=S(N-1)-S(N-2);然后要求的就是S这个序列里面有几个不同的数字。
下面把题目中的例子重新列举了一下:
思路:
先看这道题的数据A和B都是0~10^18范围内的,所以数据非常大,我之前想用模拟的方法来做,但是做不出来,后来看了网上大佬的博客,明白用辗转相除法来做简化数据,效果很好一下通过了。
首先容易发现,当i足够大时,最后一定会出现“xx0xx0...”这样的重复。所以不同数字个数一定是有限的,所以只要辗转相除法把除数弄到零就可以了。
究其原因,对于数y和x,y一定能写成kx+b的形式,在数列的生成过程中,会出现kx+b、x、(k-1)x+b、(k-2)x+b、x、...、2x+b、x、x+b、b、x,其中出现的不同数字个数就是(kx+b)/ x,之后问题变成了数x和b的问题,最后可以发现这就是一个辗转相除法的过程。每做一次辗转相除gcd(x,y),不同数字个数就多了x/ y。
还有一些特殊情况需要考虑,比如有数字是0。要考虑到其中的A和B有一个为零,或者两个都为零,我做的时候没考虑完整又WA了一次。
代码:
#include<bits/stdc++.h>
using namespace std;
int main()
{
long long int a,b,n,ans,tmp;
cin>>n;//n表示测试的组数
for(int i=1;i<=n;i++)
{
cout<<"Case #"<<i<<": ";
ans=0;
cin>>a>>b;//输入A和B,表示S0和s1,
if(a==0&&b==0)//当这两个数都等于零的时候,那么序列中不同的数只有一个
{
cout<<"1\n";
continue;
}
if(a==0||b==0)//当这两个数中只有一个为零的时候,那么序列中不同的数只有两个
{
cout<<"2\n";
continue;
}
while(b)//辗转相除法,
{
ans+=a/b;
tmp=b;
b=a%b;
a=tmp;
}
cout<<ans+1<<endl;//这个输出结果具体题目还是需要调试
}
return 0;
}