UVA-7045 Last Defence (辗转相除法)

Given two integers A and B. Sequence S is de ned as follow:
• S0 = A
• S1 = B
• Si = |S (i - 1)  — S(i - 2)| , for i >= 2
Count the number of distinct numbers in S.
Input
The rst 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.
Sample Input
2
7 4
3 5
Sample Output
Case #1: 6
Case #2: 5

题意

数列S从第3项开始每个项都为前两项的差的绝对值,输入数列的前两项,要求根据生成规则生成的数列S中有几个不同的数。

思路

刚开始想把S数列一直生成到0出现,因为只要出现0就会出现循环不会再产生新的数了,再统计不同数的个数,但是这样就会有个问题:S数组开多大?第一次开了1e5越界了,第二次开到2e6,然而超时了。查了一下发现要用辗转相除法,直接拿大的数除小的数,即需要减的次数(等于产生新的数的个数),加到结果中,最后结果便是答案。这题有个巨坑的点就是他的输出并不是样例里给的那样,而是输入完T后先打印Case #1:再输入数。就是这个坑爹格式让我wa了三次。

AC代码

#include <iostream>
using namespace std;
int main()
{
    long long int a,b,n,ans,tmp;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
    cout<<"Case #"<<i<<": ";//注意输出格式并不是样例那样
      ans=0;
      cin>>a>>b;    
      if(a==0&&b==0)//a,b都为0时特判
         {
             cout<<"1\n";
             continue;
         }
       if(a==0||b==0)//有一个为0时特判
          {
              cout<<"2\n";
              continue;
          }
      while(b)//辗转相除法
      {
          ans+=a/b;
          tmp=b;
          b=a%b;
          a=tmp;
      }
      cout<<ans+1<<endl;//注意ans+1
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/Gamer_Lee/article/details/81700157