hdu3221 Brute-force Algorithm(矩阵快速幂+欧拉降幂)

题目链接
在这里插入图片描述
在这里插入图片描述
思路:答案是一个递推式ans【n】=ans【n-1】*ans【n-2】,ans【1】=a,ans【2】=b,当n大于3的时候a和b的指数就是斐波那契数列,我们可以用矩阵快速幂算出来,但是还不行,这里的指数可能会很大,还需要用欧拉降幂在这里插入图片描述

#include<bits/stdc++.h>
using namespace std;
#define ll long long
ll fib[200];
struct mt{
    ll a[3][3];
};
mt t(mt a,mt b,ll mod){
    mt res;
    int i,j,k;
    for(i=0;i<3;i++){
        for(j=0;j<3;j++){
            res.a[i][j]=0;
            for(k=0;k<3;k++){
                res.a[i][j]+=a.a[i][k]*b.a[k][j]%mod;
                res.a[i][j]%=mod;
            }
        }
    }
    return res;
}
mt power(mt a,ll b,ll mod){
    mt res;
    int i,j;
    for(i=0;i<3;i++){
        for(j=0;j<3;j++){
            res.a[i][j]=0;
        }
    }
    res.a[0][0]=res.a[1][1]=res.a[2][2]=1;
    while(b){
        if(b&1)res=t(res,a,mod);
        b>>=1;
        a=t(a,a,mod);
    }
    return res;
}
ll feb(ll n,ll mod){
    mt temp;
    int i,j;
    for(i=0;i<3;i++){
        for(j=0;j<3;j++){
            temp.a[i][j]=0;
        }
    }
    temp.a[0][1]=temp.a[1][1]=temp.a[1][0]=1;
    mt res=power(temp,n-1,mod);
    return (res.a[0][0]+res.a[0][1])%mod;
}
ll quick(ll a,ll b,ll mod){ 
    ll ans=1;  
    a=a%mod;
    while(b!=0){
        if(b&1) ans=(ans*a)%mod;
        b>>=1;
        a=(a*a)%mod;
    }
    return ans%mod;
}
ll get_euler(ll n){
    ll res=n,a=n;
    for (ll i = 2; i*i<=a;i++){
        if(a%i==0){
            res=res/i*(i-1);
            while(a%i==0) a=a/i;
        }
    }
    if(a>1) res=res/a*(a-1);
    return res;
}
int main(){
    int T;
    fib[0] = 1;fib[1] = 1;
    for(int i=2;i<=160;i++) fib[i]=fib[i-1]+fib[i-2];
    scanf("%d",&T);
    for(int j=1;j<=T;++j)
    {
        ll a,b,n,p;
        scanf("%lld%lld%lld%lld",&a,&b,&p,&n);
        if(n==1) printf("Case #%d: %lld\n", j, a%p);
        else if(n==2) printf("Case #%d: %lld\n", j, b%p);
        else if(n==3) printf("Case #%d: %lld\n", j, a*b%p);
        else if(a==0||b==0||p==1) printf("Case #%d: %lld\n", j, 0);
        else {
            if(n<=35){
                printf("Case #%d: %lld\n", j, quick(a,fib[n-3],p)*quick(b,fib[n-2],p)%p);continue;//注意一下欧拉降幂的使用条件是指数大于等于欧拉的时候
            }
            ll x=get_euler(p);
            ll t1=feb(n-2,x),t2=feb(n-1,x);
            ll ans=quick(a,t1+x,p)%p;
            ans*=quick(b,t2+x,p)%p;
            printf("Case #%d: %lld\n", j, ans%p);
        }
    }
}
发布了283 篇原创文章 · 获赞 0 · 访问量 7321

猜你喜欢

转载自blog.csdn.net/qq_42479630/article/details/104998450
今日推荐