HDU3977 Evil teacher 求fib数列模p的最小循环节

In the math class, the evil teacher gave you one unprecedented problem! 

Here f(n) is the n-th fibonacci number (n >= 0)! Where f(0) = f(1) = 1 and for any n > 1, f(n) = f(n - 1) + f(n - 2). For example, f(2) = 2, f(3) = 3, f(4) = 5 ... 

The teacher used to let you calculate f(n) mod p where n <= 10^18 and p <= 10^9, however , as an ACMER, you may just kill it in seconds! The evil teacher is mad about this. Now he let you find the smallest integer m (m > 0) such that for ANY non-negative integer n ,f(n) = f(n + m) (mod p) . For example, if p = 2, then we could find know m = 3 , f(0) = f(3) = 1(mod 2), f(1) = f(4) (mod 2) .... 

Now the evil teacher will only give you one integer p( p <= 2* 10^9), will you tell him the smallest m you can find ?

Input

The first line is one integer T indicates the number of the test cases. (T <=20) 
Then for every case, only one integer P . (1 <= P <= 2 * 10^9, the max prime factor for P is no larger than 10^6)

Output

Output one line. 

First output “Case #idx: ”, here idx is the case number count from 1.Then output the smallest m you can find. You can assume that the m is always smaller than 2^64 .

Sample Input

5 
11 
19 
61 
17 
67890

Sample Output

Case #1: 10 
Case #2: 18 
Case #3: 60 
Case #4: 36 
Case #5: 4440

题目让我们做什么呢,求fib数列模p的最小循环节,但是这个题目的素数一定是小于10^6,所以有下面这个水水的做法

对每一个形如p^k的数计算循环节,它们的最小公倍数就是n的循环节长度(当然这里面涉及到CRT等等方面的基础)。那么现在问题就是计算p^k的循环节,这个问题可以进一步简化成求G(p)*p^(k-1)

求fib数列模p(p是素数)的最小循环节方法:

暴力枚举fib[i]%p==0的最小的i,然后记录pos=i+1,设a为fib[i]%p==0的前一位数,即a=fib[i-1]

那么我们知道fib数列模p的最小循环节长度一定是pos*x,那么也就是说现在要求一个最小的数x

满足,

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll Lcm(ll a,ll b)
{
    return a/__gcd(a,b)*b;
}
inline ll Pow(ll a,ll b,ll p)
{
    ll ans=1;
    for(; b; b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;
    return ans;
}
const int N=1e6+5;
int prime[N],tot,vis[N];
inline void Pre()
{
    for(int i=2; i<N; i++)
    {
        if(!vis[i]) prime[++tot]=i;
        for(int j=1; j<=tot&&1LL*prime[j]*i<N; j++)
        {
            vis[prime[j]*i]=1;
            if(i%prime[j]==0)break;
        }
    }
}
inline ll calc(ll p)
{
    ll a=3,f1=1,f2=1,f3=2%p;
    while(f3) f1=f2,f2=f3,f3=(f1+f2)%p,a++;
    ll ans=p-1;
    for(int i=1; 1LL*i*i<p; i++)
        if((p-1)%i==0)
        {
            if(Pow(f2,i,p)==1) ans=min(ans,1LL*i);
            if(Pow(f2,(p-1)/i,p)==1) ans=min(ans,1LL*(p-1)/i);
        }
    return ans*a;
}
inline ll Solve(ll n)
{
    ll ans=0;
    for(int i=1; prime[i]<=n; i++)
        if(n%prime[i]==0)
        {
            ll tmp=1;
            while (n%prime[i]==0) n/=prime[i],tmp*=prime[i];
            tmp=tmp/prime[i]*calc(prime[i]);
            ans=!ans?tmp:Lcm(ans,tmp);
        }
    return ans;
}
int main()
{
    int T,n,ca=0;
    Pre(),scanf("%d",&T);
    while(T--)scanf("%d",&n),printf("Case #%d: %I64d\n",++ca,n==1?1:Solve(n));
    return 0;
}

数字变大呢,就是解特征值了,不会啊

1195 斐波那契数列的循环节

posted @ 2018-10-11 15:28  暴力都不会的蒟蒻  阅读(481)  评论(0编辑  收藏  举报