Fib数模n的循环节

来源:互联网 发布:双11销售额包括淘宝吗 编辑:程序博客网 时间:2024/06/07 12:25

对于一个正整数n,我们求Fib数模n的循环节的长度的方法如下:


    (1)把n素因子分解,即

    (2)分别计算Fib数模每个的循环节长度,假设长度分别是

    (3)那么Fib模n的循环节长度


从上面三个步骤看来,貌似最困难的是第二步,那么我们如何求Fib模的循环节长度呢?

 

     这里有一个优美的定理:Fib数模的最小循环节长度等于,其中表示Fib数模素数的最小循环节长度。可以看出我们现在最重要的就是求

 

 

对于求我们利用如下定理:

 

   如果5是模的二次剩余,那么循环节的的长度是的因子,否则,循环节的长度是的因子。


顺便说一句,对于小于等于5的素数,我们直接特殊判断,loop(2)=3,loop(3)=8,loop(5)=20。


那么我们可以先求出所有的因子,然后用矩阵快速幂来一个一个判断,这样时间复杂度不会很大。

 

以上来自 点击打开链接


hdu3977

Evil teacher

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 356    Accepted Submission(s): 167


Problem Description
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
 



给定p的值  对于一个任意一个n  找到最小的m 使得F(n)=F(n+m)(mod p)

模版题  贴一个代码

#include <cstdio>#include <iostream>#include <cstring>#include <cmath>#include <algorithm>#include <string.h>#include <string>#define MEM(a,x) memset(a,x,sizeof a)#define eps 1e-8#define MAXN 10010#define INF 0x7fffffff#define ll unsigned long long#define bug cout<<"here"<<endl;#define fread freopen("ceshi.txt","r",stdin)#define fwrite freopen("out.txt","w",stdout)using namespace std;const int M=2;struct Matrix{    ll m[M][M];};Matrix A;Matrix I={1,0,0,1};Matrix multi(Matrix a,Matrix b,ll MOD){    Matrix c;    for(int i=0;i<M;i++)    {        for(int j=0;j<M;j++)        {            c.m[i][j]=0;            for(int k=0;k<M;k++)                c.m[i][j]=(c.m[i][j]%MOD+(a.m[i][k]%MOD)*(b.m[k][j]%MOD)%MOD)%MOD;            c.m[i][j]%=MOD;        }    }    return c;}Matrix power(Matrix a,ll k,ll MOD){    Matrix ans=I,p=a;    while(k)    {        if(k&1)        {            ans=multi(ans,p,MOD);            k--;        }        k>>=1;        p=multi(p,p,MOD);    }    return ans;}ll gcd(ll a,ll b){    if(b==0) return a;    return gcd(b,a%b);}const int N=400005;const int NN=5005;ll num[NN],pri[NN];ll fac[NN];int cnt,c;bool prime[N];int p[N];int k;void isprime(){    k=0;    MEM(prime,1);    for(int i=2;i<N;i++)    {        if(prime[i])        {            p[k++]=i;            for(int j=i+i;j<N;j+=i)                prime[j]=false;        }    }}ll quick_mod(ll a,ll b,ll m){    ll ans=1;    a%=m;    while(b)    {        if(b&1)        {            ans=ans*a%m;            b--;        }        b>>=1;        a=a*a%m;    }    return ans;}ll legendre(ll a,ll p){    if(quick_mod(a,(p-1)>>1,p)==1)  return 1;    else return -1;}void Solve(ll n,ll pri[],ll num[]){    cnt=0;    ll t=(ll)sqrt(1.0*n);    for(int i=0;p[i]<=t;i++)    {        if(n%p[i]==0)        {            int a=0;            pri[cnt]=p[i];            while(n%p[i]==0)            {                a++;                n/=p[i];            }            num[cnt]=a;            cnt++;        }    }    if(n>1)    {        pri[cnt]=n;        num[cnt]=1;        cnt++;    }}void Work(ll n){    c=0;    ll t=(ll)sqrt(1.0*n);    for(int i=1;i<=t;i++)    {        if(n%i==0)        {            if(i*i==n)  fac[c++]=i;            else            {                fac[c++]=i;                fac[c++]=n/i;            }        }    }}ll find_loop(ll n){    Solve(n,pri,num);    ll ans=1;    for(int i=0;i<cnt;i++)    {        ll record=1;        if(pri[i]==2)            record=3;        else if(pri[i]==3)            record=8;        else if(pri[i]==5)            record=20;        else        {            if(legendre(5,pri[i])==1)                Work(pri[i]-1);            else                Work(2*(pri[i]+1));            sort(fac,fac+c);            for(int k=0;k<c;k++)            {                Matrix a=power(A,fac[k]-1,pri[i]);                ll x=(a.m[0][0]%pri[i]+a.m[0][1]%pri[i])%pri[i];                ll y=(a.m[1][0]%pri[i]+a.m[1][1]%pri[i])%pri[i];                if(x==1&&y==0)                {                    record=fac[k];                    break;                }            }        }        for(int k=1;k<num[i];k++)            record*=pri[i];        ans=ans/gcd(ans,record)*record;    }    return ans;}void Init(){    A.m[0][0]=1;    A.m[0][1]=1;    A.m[1][0]=1;    A.m[1][1]=0;}int main(){    ll n;    Init();    isprime();    int tc;    int cnt=1;    scanf("%d",&tc);    while(tc--)    {        cin>>n;        printf("Case #%d: %llu\n",cnt++,find_loop(n));    }    return 0;}


hnu 13164 

ArnoldTime Limit: 8000ms, Special Time Limit:20000ms, Memory Limit:65536KBTotal submit users: 8, Accepted users: 6Problem 13164 : No special judgementProblem description

Do you know Vladimir Arnold? He's a mathematician who demonstrated an image transformation method called arnold transformation, which could shuffle all pixels in an image, and after a serials of this transformation, the image would be transformed to its original form.
The transformation method is quite simple. For a given image with N × N pixels (Width and height are both equal to N), a pixel at location (x, y) will be shuffled to location ((x + y) % N, (x + 2 × y) % N) (0 ≤ x < N, 0 ≤ y < N). In one step of transformation, all N × N pixels will be shuffled to new corresponding location, making the image a chaotic one. You can do the transformation as many times as you can.
The arnold transformation is very interesting. For every image of size N × N, after finite steps of transformation, the image will become exact the same as the original one. The minimum number of steps which make every possible image become the same as origin will be called as period of arnold transformation. For a given N, can you calculate the period?

Input

There will be about 200 test cases. For each test case, there will be an integer N in one line. Here N (2 ≤ N ≤ 4000000000) equals to width and height of images.

Output

For each test case, please calculate the period of arnold transformation and output it in one line.

Sample Input
112941
Sample Output
5720

思路  假设初始位置是(x0,x1)  经过变换之后的位置是(x2,x3)

由变换公示可得 x2=x0+x1  x3=x0+x1*2=(x0+x1)+x1=x1+x2 

给定n(模的值)  求最小循环节

这个跟上一题的区别就在于要除以2

初始为(f0,f1) 然后变为(f2,f3)……(f(n-1),fn)

同一个坐标中有两个Fib数列的值  所以 求要经过多少个坐标变换 需要除以2

#include <iostream>#include <string.h>#include <algorithm>#include <stdio.h>#include <math.h>using namespace std;typedef unsigned long long LL;const int M = 2;struct Matrix{    LL m[M][M];};Matrix A;Matrix I = {1,0,0,1};Matrix multi(Matrix a,Matrix b,LL MOD){    Matrix c;    for(int i=0; i<M; i++)    {        for(int j=0; j<M; j++)        {            c.m[i][j] = 0;            for(int k=0; k<M; k++)                c.m[i][j] = (c.m[i][j]%MOD + (a.m[i][k]%MOD)*(b.m[k][j]%MOD)%MOD)%MOD;            c.m[i][j] %= MOD;        }    }    return c;}Matrix power(Matrix a,LL k,LL MOD){    Matrix ans = I,p = a;    while(k)    {        if(k & 1)        {            ans = multi(ans,p,MOD);            k--;        }        k >>= 1;        p = multi(p,p,MOD);    }    return ans;}LL gcd(LL a,LL b){    return b? gcd(b,a%b):a;}const int N = 400005;const int NN = 5005;LL num[NN],pri[NN];LL fac[NN];int cnt,c;bool prime[N];int p[N];int k;void isprime(){    k = 0;    memset(prime,true,sizeof(prime));    for(int i=2; i<N; i++)    {        if(prime[i])        {            p[k++] = i;            for(int j=i+i; j<N; j+=i)                prime[j] = false;        }    }}LL quick_mod(LL a,LL b,LL m){    LL ans = 1;    a %= m;    while(b)    {        if(b & 1)        {            ans = ans * a % m;            b--;        }        b >>= 1;        a = a * a % m;    }    return ans;}LL legendre(LL a,LL p){    if(quick_mod(a,(p-1)>>1,p)==1) return 1;    else                           return -1;}void Solve(LL n,LL pri[],LL num[]){    cnt = 0;    LL t = (LL)sqrt(1.0*n);    for(int i=0; p[i]<=t; i++)    {        if(n%p[i]==0)        {            int a = 0;            pri[cnt] = p[i];            while(n%p[i]==0)            {                a++;                n /= p[i];            }            num[cnt] = a;            cnt++;        }    }    if(n > 1)    {        pri[cnt] = n;        num[cnt] = 1;        cnt++;    }}void Work(LL n){    c = 0;    LL t = (LL)sqrt(1.0*n);    for(int i=1; i<=t; i++)    {        if(n % i == 0)        {            if(i * i == n) fac[c++] = i;            else            {                fac[c++] = i;                fac[c++] = n / i;            }        }    }}LL find_loop(LL n){    Solve(n,pri,num);    LL ans=1;    for(int i=0; i<cnt; i++)    {        LL record=1;        if(pri[i]==2)            record=3;        else if(pri[i]==3)            record=8;        else if(pri[i]==5)            record=20;        else        {            if(legendre(5,pri[i])==1)                Work(pri[i]-1);            else                Work(2*(pri[i]+1));            sort(fac,fac+c);            for(int k=0; k<c; k++)            {                Matrix a = power(A,fac[k]-1,pri[i]);                LL x = (a.m[0][0]%pri[i]+a.m[0][1]%pri[i])%pri[i];                LL y = (a.m[1][0]%pri[i]+a.m[1][1]%pri[i])%pri[i];                if(x==1 && y==0)                {                    record = fac[k];                    break;                }            }        }        for(int k=1; k<num[i]; k++)            record *= pri[i];        ans = ans/gcd(ans,record)*record;    }    return ans;}void Init(){    A.m[0][0] = 1;    A.m[0][1] = 1;    A.m[1][0] = 1;    A.m[1][1] = 0;}int main(){    LL n;    Init();    isprime();    while(cin>>n)        cout<<find_loop(n)/2<<endl;    return 0;}









0 0