ACdream 1124 喵喵的遺憾

題意:

中文題。。。。


解題思路:

fibonacci 模 p 的最小週期.

假設NP(m)表示m的最小週期,滿足:

        NP(ab) = lcm(NP(a),NP(b)); 當且僅當(a,b)= 1;

        NP(p^d) = NP(p)*p^(d-1);當且僅當p爲素數

  如果p爲素數,則

        (p%10==2) 週期爲NP(p) =  3

        (p%10==5) 週期爲NP(p) = 20

        (p%10==1||p%10==9) NP(p) | p-1 

        (爲p-1的構成周期最小因子)

        (p%10==3||p%10==7) NP(p) | 2*p+2   

        (爲2*p+2的構成周期最小因子)

           

根據上述公式,可求關於mod p的最小週期爲H,然後求關於mod H的最小週期爲S

原式子    F[F[F[N]]]%P        化爲     F[F[F[N]%S]%H]%P;

再利用矩陣即可求


注意:

要用llu 才能過,lld 可能會wa 

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
typedef unsigned long long  LL;
#define MAXSZ 50000
#define MAXN 2000000000
void dfs(int ind,LL pro,int cn,LL &ans,bool &flag,LL mod);
LL P;
bool vis[MAXSZ]={};
int p[5000],cnt;
LL fac[5000];
LL A[2][2],E[2][2];
void getpri(){
    int n = (int)sqrt(MAXN+0.5);
    cnt = 0;
    for(int i=2;i<=n;++i){
        if(vis[i])continue;
        p[cnt++] = i;
        for(int j=2*i;j<=n;j+=i){
            vis[j] = true;
        }
    }
}
//void init(){
//    A[0][0] = A[0][1]=A[1][0] = 1;
//    A[1][1] = 0;
//    E[0][0] = E[1][1] = 1;
//    E[0][1] = E[1][0] = 0;
//}
LL gcd(LL a,LL b){
    if(!b)return a;
    return gcd(b,a%b);
}
void quick_mod(LL m,LL mod){
    
    A[0][0] = 1;//A[0][1]=A[1][0] = 1;
    A[1][1] = 1;
    A[1][0] = A[0][1] = 0;
    E[0][0] =1; E[1][1] = 0;
    E[0][1] = E[1][0] = 1;
    if(m<=0)return;
    LL tmp1,tmp2,tmp3,tmp4;
    while(m){
        if(m&1){
            tmp1 = (A[0][0]*E[0][0]+E[1][0]*A[0][1])%mod;
            tmp2 = (A[0][0]*E[0][1]+A[0][1]*E[1][1])%mod;
            tmp3 = (A[1][0]*E[0][0]+A[1][1]*E[1][0])%mod;
            tmp4 = (A[1][0]*E[0][1]+A[1][1]*E[1][1])%mod;
            A[0][0] = tmp1; //A[0][0];
            A[0][1] = tmp2;//A[0][1];
            A[1][0] = tmp3;
            A[1][1] = tmp4;
        }
        m>>=1;
        if(!m)break;
        tmp1 = (E[0][0]*E[0][0]+E[1][0]*E[0][1])%mod;
        tmp2 = (E[0][0]*E[0][1]+E[0][1]*E[1][1])%mod;
        tmp3 = (E[1][0]*E[0][0]+E[1][1]*E[1][0])%mod;
        tmp4 = (E[1][0]*E[0][1]+E[1][1]*E[1][1])%mod;
        E[0][0] = tmp1;
        E[0][1] = tmp2;
        E[1][0] = tmp3;
        E[1][1] = tmp4;
        //m>>=1;
    }
}
bool isok(LL m,LL mod){
    quick_mod(m,mod);
    if((A[0][0]+A[0][1])%mod==(1%mod)&&(A[1][0]+A[1][1])%mod==(1%mod)){
        return true;
    }
    return false;
}
void dfs(int ind,LL pro,int cn,LL &ans,bool &flag,LL mod){
    if(flag){
        if(pro>ans)
            return ;
    }
    if(ind==cn){
        if(isok(pro,mod)){
            if(flag){
                if(ans>pro)ans = pro;
            }
            else {
                flag = true;
                ans = pro;
            }
        }
        return;
    }
    dfs(ind+1,pro,cn,ans,flag,mod);
    dfs(ind+1,pro*fac[ind],cn,ans,flag,mod);
}
LL getfac(LL num,LL mod){
    int cn = 0;
    for(int i=0;i<cnt;++i){
        if(num<p[i])break;
        while(num%p[i]==0){
            num/=p[i];
            fac[cn++] = p[i];
        }
    }
    if(num!=1){
        fac[cn++] = num;
    }
    LL ans=0;
    bool flag = false;
    //dfs(0,1,cn,ans,false,mod);
    dfs(0,1,cn,ans,flag,mod);
    return ans;
}
LL getNP(LL N){
    int tmp = N%10;
    if(tmp==2){
        return 3;
    }
    if(tmp==5){
        return 20;
    }
    if(tmp==1||tmp==9){
        return getfac(N-1,N);
    }
    if(tmp==3||tmp==7){
        return getfac(2*N+2,N);
    }
    return  1;
}
LL getT(LL num){
    if(num==1){
        return 1;
    }
    LL pw = 1,pd;
    LL ans = 1;
    LL g;
    for(int i=0;i<cnt;++i){
        if(num<p[i])break;
        if(num%p[i]==0){
            pw =1;
            while(num%p[i]==0){
                num/=p[i];
                pw*=p[i];
            }
            pw/=p[i];
            pd = getNP(p[i])*pw;
            g = gcd(ans,pd);
            ans = (ans/g)*pd;
        }
    }
    if(num!=1){
        pd = getNP(num);
        g = gcd(ans,pd);
        ans = (ans/g)*pd;
    }
    return ans;
}
int main(){
    int T;
    

    getpri();
   
   // int cas = 0;
    LL N;
//    LL up = 10000;
//    for(LL i = 1000000000;i>=2;--i){
//        LL T1,T2;
//        T1 = getT(i);
//        LL tmp0=1,tmp1=1,tmp2;
//        LL  c=1;
//        LL K =i;
//        while(1){
//            tmp2 = tmp1;
//            tmp1 = (tmp0 + tmp1)%K;
//            c++;
//            tmp0 = tmp2%K;
//            if(tmp0==1&&tmp1==1){
//                T2 = c-1;
////                printf("%lld\n",c-1);
//                break;
//            }
//        }
//        printf("Case: %lld\n",i);
//        if(T1!=T2){
//            printf("%lld\n",i);
//            break;
//        }
//    }
//    printf("YES\n");
     scanf("%d",&T);
    while(T--){
       // init();
        scanf("%llu%llu",&N,&P);
        LL S =getT(P);
        LL H = getT(S);
        //LL F = getT(H);
        quick_mod(N, H);
        LL ans1 = (A[1][1]+A[1][0])%H;
        quick_mod(ans1, S);
        LL ans2 = (A[1][1]+A[1][0])%S;
        quick_mod(ans2, P);
        LL ans3 = (A[1][1]+A[1][0])%P;
        //printf("Case #%d: %lld\n",++cas,ans);
        printf("%llu\n",ans3);

    }
    return 0;
}






發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章