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。
还有一些特殊情况需要考虑,比如有数字是0。
参考代码:
#include <iostream>
using namespace std;
long long a, b, ans;
int nCase, cCase;
long long calc(long long a, long long b) {
long long ret = 0;
while (b) {
long long t = b;
ret += a / b;
b = a % b;
a = t;
}
return ret + 1;
}
int main() {
ios::sync_with_stdio(false);
cin >> nCase;
while (nCase--) {
cin >> a >> b;
if (a == 0 && b == 0) {
ans = 1;
} else if (a == 0 || b == 0) {
ans = 2;
} else {
ans = calc(a, b);
}
cout << "Case #" << ++cCase << ": " << ans << endl;
}
return 0;
}