hdu2814

链接:点击打开链接

题意:求出F(a^b)^(F(a^b)^(n-1))%c(F为斐波那契数的值)

代码:

#include <iostream>
#include <stdio.h>
#include <algorithm>
#include <math.h>
using namespace std;
unsigned long long f[20005];                    //注意要使用无符号形
unsigned long long phi(unsigned long long n){   //欧拉函数值
    unsigned long long sum=n,i;
    for(i=2;i*i<=n;i++){
        if(n%i==0){
            sum-=sum/i;
            while(n%i==0)
            n/=i;
        }
    }
    if(n>1)
    sum-=sum/n;
    return sum;
}
unsigned long long quickmod(unsigned long long a,unsigned long long b,unsigned long long m){
    unsigned long long sum=1;                   //快速幂
    a=a%m;
    while(b){
        if(b&1)
        sum=sum*a%m;
        b>>=1;
        a=a*a%m;
    }
    return sum;
}
unsigned long long loop(unsigned long long m){
    unsigned long long i;                       //求斐波那契数的循环节
    f[0]=0;f[1]=1;f[2]=1;
    for(i=3;;i++){
        f[i]=(f[i-1]+f[i-2])%m;
        if(f[i]==f[1]&&f[i-1]==f[0])
        return i-1;
    }
}
int main(){                                     //这道题主要运用了两个性质:
    unsigned long long a,b,n,c,i,j,l,ph,cur,sum;//1.a^b≡(amodc)^bmodϕ(c)+ϕ(c)(modc),b>=ϕ(c) ϕ(c)为c的欧拉函数值
    int k,t;                                    //2.斐波那契数列有一个性质,它的n次方取模会出现一个循环节.假设循环节长度为len,则F(a^b)modc=F(a^bmodlen)modc
    cin>>t;
    for(k=1;k<=t;k++){
        cin>>a>>b>>n>>c;
        printf("Case %d: ",k);
        if(c==1){                               //c等于0时,模一定为0
            printf("0\n");
            continue;
        }                                       //根据以上性质本题变为求F(a^b)^(F(a^b)^(n-1))%c(F()为斐波那契)
        ph=phi(c);                              //先求出欧拉函数值
        l=loop(c);                              //求循环
        cur=quickmod(a,b,l);
        cur=f[cur];                             //求出F[a^b%len]
        if(ph==1){                              //欧拉函数为1时单独考虑
            cout<<quickmod(cur,n-1,c)<<endl;
            continue;
        }
        l=loop(ph);
        sum=quickmod(a,b,l);
        sum=f[sum];                             //求出关于欧拉函数值F[a^b%len]
        sum=quickmod(sum,n-1,ph)+ph;
        cur=quickmod(cur,sum,c);                //从而求出结果
        cout<<cur<<endl;
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值