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; }
CF GYM 100548 Last Defence(2014ACM西安现场赛Problem K)
原文地址:http://blog.csdn.net/wujysh/article/details/43085217