HDU 3221 Brute-force Algorithm【矩陣快速冪】【歐拉降冪】

題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=3221
AC代碼:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod=10000;
ll n,p,aa,b;
const ll maxn=1e6+10;
ll phi[maxn];
struct mat
{
    ll a[2][2];
};
mat mat_mul(mat x,mat y)
{
    mat res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++){
                res.a[i][j]=(res.a[i][j]+x.a[i][k]*y.a[k][j]);
                if(res.a[i][j]>phi[p])
                    res.a[i][j]=res.a[i][j]%phi[p]+phi[p];//在這裏歐拉降冪
            }
    return res;
}
mat mat_pow(ll n)
{
    mat c,res;
    c.a[0][0]=c.a[0][1]=c.a[1][0]=1;
    c.a[1][1]=0;
    memset(res.a,0,sizeof(res.a));
    for(int i=0;i<2;i++)
        res.a[i][i]=1;
    while(n)
    {
        if(n&1)
            res=mat_mul(res,c);
        c=mat_mul(c,c);
        n=n>>1;
    }
    return res;
}
void eulr()
{
    for(int i=0;i<maxn;i++){
        phi[i]=i;
    }
    for(int i=2;i<maxn;i++){
        if(phi[i]==i){
            for(int j=i;j<maxn;j+=i){
                phi[j]=phi[j]/i*(i-1);
            }
        }
    }
}

ll qpow(ll x,ll y,ll mo)
{
    ll ans=1;
    while(y){
        if(y&1)
            ans=ans*x%mo;
        x=x*x%mo;
        y>>=1;
    }
    return ans;
}
int main()
{
    int t;
    eulr();//預處理,不然會超時
    //cout<<mat_pow(2)<<endl;
    scanf("%d",&t);
    int Case=0;
    while(t--){
        scanf("%lld%lld%lld%lld",&aa,&b,&p,&n);
     //   cout<<"Case #"<<++Case<<": ";
        ll ta,tb;
        ll ans;
        if(n==1){//特判一下n==1,2情況
            ans=aa%p;
        }
        else if(n==2){
            ans=b%p;
        }
        else{
            mat tmp=mat_pow(n-2);
            ta=tmp.a[0][1];//斐波那契數列
            tb=tmp.a[0][0];
            ans=qpow(aa,ta,p)*qpow(b,tb,p)%p;
        }
        printf("Case #%d: %lld\n",++Case,ans);
    }

    return 0;
}

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