• 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
    ",++ca,n==1?1:Solve(n));
        return 0;
    }

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

    1195 斐波那契数列的循环节

  • 相关阅读:
    方法参数的传递方式
    方法设计
    接口
    SQL 安装MySQL
    Windows 10 安装 wordpress
    Windows10安装PHP7+Apache 2.4
    做一个增删改查的工程
    清除缓存
    创建POJO
    VI快捷键
  • 原文地址:https://www.cnblogs.com/BobHuang/p/9772686.html
Copyright © 2020-2023  润新知