首页 > 代码库 > UVALive 7045 Last Defence
UVALive 7045 Last Defence
ProblemK. Last Defence
Description
Given two integersA and B. Sequence S is defined as follow:
? S0 = A
? S1 = B
? Si = |Si?1 ?Si?2| for i ≥ 2
Count the number ofdistinct numbers in S.
Input
The first line ofthe input gives the number of test cases, T. T test cases follow. Tis about 100000.
Each test caseconsists of one line - two space-separated integers A, B. (0 ≤ A, B≤ 1018).
Output
For each test case,output one line containing “Case #x: y”, where x is the test casenumber (starting from 1) and y is the number of distinct numbers inS.
Samples
Sample Input |
Sample Output |
2 7 4 3 5 |
Case #1: 6 Case #2: 5 |
知识点:
Ad-Hoc,辗转相除法。
题目大意:
给定数列S的首两项,要求之后的各项满足Si= |Si?1 ? Si?2|(前两项差值的绝对值)。问整个数列S中不同的数字个数。
解题思路:
首先容易发现,当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。
代码:
1 #include "cstdio" 2 #include "algorithm" 3 #include "cstring" 4 #include "queue" 5 #include "cmath" 6 #include "vector" 7 #include "map" 8 #include "stdlib.h" 9 typedef long long ll; 10 using namespace std; 11 const int N=1e5+5; 12 const int mod=1e9+7; 13 14 15 int main() 16 { 17 int t; 18 scanf("%d",&t); 19 ll a,b,ans; 20 for(int i=1;i<=t;i++){ 21 scanf("%lld%lld",&a,&b); 22 ans=1; 23 if(a==b) 24 { 25 if(a==0) printf("Case #%d: 1\n",i); 26 else printf("Case #%d: 2\n",i); 27 continue; 28 } 29 else if(a==0||b==0) printf("Case #%d: 2\n",i); 30 else 31 { 32 if(b>a) {int t=a;a=b;b=t;} 33 while (b){ 34 ll t=b; 35 ans+=a/b; 36 b=a%b; 37 a=t; 38 } 39 } 40 printf("Case #%d: %lld\n",i,ans); 41 42 } 43 44 return 0; 45 }
UVALive 7045 Last Defence