CF GYM 100548 Last Defence
题目链接:https://vjudge.net/contest/362170#problem/B
题目大意:
给定数列S的首两项,要求之后的各项满足S[i] = |S[i-1] - S[i-2]|(前两项差值的绝对值)。问整个数列S中不同的数字个数。
想法:
首先容易发现,当i足够大时,最后一定会出现“xx0xx0...”这样的重复。所以不同数字个数一定是有限的。
对于任何一个大于X的Y,我们都可以把Y表示成 KX + B
这样我们可以一直递推下去 (K-1)X + B,(K-2)X + B .... B . 这样我们发现这个从Y -> B 贡献是 K个,当B是0的时候就可以停下来了
#pragma GCC optimize(3,"Ofast","inline")//O3优化 #pragma GCC optimize(2)//O2优化 #include <algorithm> #include <string> #include <string.h> #include <vector> #include <map> #include <stack> #include <set> #include <queue> #include <math.h> #include <cstdio> #include <iomanip> #include <time.h> #include <bitset> #include <cmath> #include <sstream> #include <iostream> #include <cstring> #define LL long long #define ls nod<<1 #define rs (nod<<1)+1 #define pii pair<int,int> #define mp make_pair #define pb push_back #define INF 0x3f3f3f3f const double eps = 1e-10; const int maxn = 2e5 + 10; const LL mod = 1e9 + 7; int sgn(double a){return a < -eps ? -1 : a < eps ? 0 : 1;} using namespace std; int main() { int T; scanf("%d",&T); int t = 1; while (T--) { LL a,b; scanf("%lld%lld",&a,&b); if (a == 0 && b == 0) { printf("Case #%d: 1\n",t++); continue; } if (a == 0 || b == 0) { printf("Case #%d: 2\n",t++); continue; } LL ans = 2; while (1) { if (a < b) swap(a,b); if (b == 0) break; ans += a / b; a = a % b; } ans--; printf("Case #%d: %lld\n",t++,ans); } return 0; }