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
所以
ax≡axmodφ(p)modp
用快速幂计算就好了。
如果不互质呢?
设
g=gcd(a,p),a′=a/g,p′=b/g
,ans为答案,则
gx∗a′x≡ansmodp′∗g
同时除以g
gx−1∗a′x≡ansgmodp′
这时候 gcd(a′,p′)=1 就可以用最上面的方法求出来了。
然后?就没有然后了。
注意,因为有模,x可以等于0,这时
gx−1
要用逆元。
这次真的没有了。
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));
}
}
(为什么每次/号都会带出一片绿色?(>_<)强迫症表示不爽~)
另,其实这是水法,为什么
g−1
一定存在!!!
@WerKeyTom_FTD
又另,@能用吗?(我too young)