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;
}

猜你喜欢

转载自www.cnblogs.com/-Ackerman/p/12508124.html