bzoj1409: Password

来源:互联网 发布:陈奕迅 必听 知乎 编辑:程序博客网 时间:2024/06/15 20:35

传送门
其实题目就是求p^F[n]
发现p,q互质,于是我们开心的大力用欧拉函数和矩阵快速幂
据说暴力求欧拉函数会被卡?

#include<cmath>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#define ll long long#define N 100005using namespace std;int T,n,p,q,mo,ans,pri[N],fl[N],tot;ll E[2][2]={{0,0},{0,0}};ll I[2][2]={{1,0},{0,1}};ll B[2][2]={{0,1},{1,1}};struct mat{    ll a[2][2];    mat(ll _[2][2]){        memcpy(a,_,sizeof(a));    }    ll* operator [] (int x){        return a[x];    }    friend mat operator *(mat x,mat y){        mat z(E);        for (int i=0;i<2;i++)            for (int j=0;j<2;j++)                for (int k=0;k<2;k++)                    z[i][j]=(z[i][j]+x[i][k]*y[k][j])%mo;        return z;    }   };mat power(mat x,int y){    mat s(I);    for (;y;y/=2,x=x*x)        if (y&1) s=s*x;    return s;}void pre(){    for (int i=2;i<=N;i++){        if (!fl[i]) pri[++tot]=i;        for (int j=1;j<=tot&&i*pri[j]<=N;j++){            fl[i*pri[j]]=1;            if (i%pri[j]) continue;        }    }}int phi(int x){    int s=x;    for (int i=1;pri[i]*pri[i]<=x;i++)        if (x%pri[i]==0){            s-=s/pri[i];            while (x%pri[i]==0)                x/=pri[i];        }    if (x!=1) s-=s/x;    return s;}ll power(ll x,int y){    ll s=1;    for (;y;y/=2,x=x*x%q)        if (y&1) s=s*x%q;    return s;}int main(){    pre();    scanf("%d%d",&T,&p);    while (T--){        scanf("%d%d",&n,&q);        mo=phi(q);        ans=power(B,n)[1][0];        printf("%d\n",(int)power(p,ans)%q);    }}
原创粉丝点击