Colossal Fibonacci Numbers! UVA 11582 寻找循环节

/**
题目:Colossal Fibonacci Numbers! UVA 11582
链接:https://vjudge.net/problem/UVA-11582
题意:f[0] = 1, f[1] = 1; 给定一个n,求f[a^b]%n的结果。a,b达到2^64 - 1大。
思路:a,b很大,用无符号长整型;我还是太菜了,自己没想出来。这道题很显然是找循环节的题。但我不知怎么找。
lrj P316
思路就是,由于fibonacci数是由前两个数相加得来,又%n;所以所有fibonacci取余后,结果都在1000以内。
两个连续的数最多只有1000×1000种。所以循环节就会出现。
我一开始以为可能是混循环或者纯循环两种情况。然后搞得很麻烦。
实际上只有一种情况:纯循环;
证明:假设存在混循环,f[0] f[1] f[2] ... f[i] f[i+1] ... f[j] f[j+1]...
f[i]==f[j], f[i+1]==f[j+1]; 由于f[i+1] = f[i]+f[i-1] , f[j+1] = f[j]+f[j-1]

所以显然f[i-1]==f[j-1]; 那么f[i-1] f[i]   f[j-1] f[j]又是一个循环节。同理一直推到f[0] f[1]开始的循环。

所以都是纯循环。

*/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <set>
#include <vector>
#include <cmath>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 1e3+10;
const double eps = 1e-6;
int f[maxn*maxn];
ull a, b;
int n;
ll PowMod(int mod)
{
    ll p = 1;
    a %= mod;
    ll x = a;
    while(b>0){
        if(b&1) p = p*x%mod;
        x = x*x%mod;
        b >>= 1;
    }
    return p;
}
void solve()
{
    f[0] = 0;
    f[1] = 1;//n = 1 的时候 这里为0
    int ed;
    for(int i = 2; i <= n*n; i++){
        f[i] = f[i-1]+f[i-2];
        f[i] %= n;
        if(f[i-1]==f[0]&&f[i]==f[1]){
            ed = i-1; ///[st, ed]
            break;
        }
    }
    ll pos = PowMod(ed);
    printf("%d
",f[pos]);
}
int main()
{
    int T;
    cin>>T;
    while(T--){
        scanf("%llu%llu%d",&a,&b,&n);
        if(a==0||n==1){///处理0^ei的情况,以及对1取模值肯定为0;
            printf("0
"); continue;
        }
        solve();
    }
    return 0;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/6735815.html