【GDOI三校联考】Pow

Description

给出t组询问,每组询问给出n个数,a1~an,和模数p,求a1^a2^….an mod p的值。
t<=100,ai,p<10^7,n<=20

Solution

这样我们只需要快速计算 axmodp 的值就可以了。
如果 gcd(a,p)=1 的话,那么 aφ(p)1modp
所以 axaxmodφ(p)modp
用快速幂计算就好了。
如果不互质呢?
g=gcd(a,p),a=a/gp=b/g ,ans为答案,则

gxaxansmodpg

同时除以g
gx1axansgmodp

这时候 gcd(a,p)=1 就可以用最上面的方法求出来了。
然后?就没有然后了。

注意,因为有模,x可以等于0,这时 gx1 要用逆元。
这次真的没有了。

Code

#include<cstdio>
#include<cstring>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
#define N 10000000
using namespace std;
ll n,p,x,ty,b[25],phi[N+5];
int bz[N+5],pr[N],tot;
ll mi(ll x,ll y,ll p) {
    ll z;
    for(z=1;y;y / =2) {
        if (y%2) z=z*x%p;
        x=x*x%p;
    }
    return z;
}
int gcd(int x,int y) {
    return (y)?gcd(y,x%y):x;
}
ll pow(ll x,ll y) {
    if (x>n) return 1;
    ll g=gcd(b[x],y);y/=g;b[x]/=g;
    ll t=pow(x+1,phi[y]),ans;
    if (t) ans=mi(g,t-1,y)*mi(b[x],t,y)%y;
    else ans=mi(g,phi[y]-1,y)*mi(b[x],t,y)%y;
    return ans*g;
}
int main() {
    phi[1]=1;
    fo(i,2,N) {
        if (!bz[i]) pr[++tot]=i,phi[i]=i-1;
        fo(j,1,tot) {
            int k=i*pr[j];if (k>N) break;bz[k]=1;
            if (!(i%pr[j])) {
                phi[k]=phi[i]*pr[j];break;
            }
            phi[k]=phi[i]*(pr[j]-1);
        }
    } 
    for(scanf("%lld",&ty);ty;ty--) {
        scanf("%lld%lld",&n,&p);
        fo(i,1,n) scanf("%lld",&b[i]);
        printf("%lld\n",pow(1,p));
    }
}

(为什么每次/号都会带出一片绿色?(>_<)强迫症表示不爽~)
另,其实这是水法,为什么 g1 一定存在!!!
@WerKeyTom_FTD
又另,@能用吗?(我too young)

你可能感兴趣的:(gcd,快速幂,pow,欧拉定理,GDOI三校联考)