模板题不解释
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
#include<bits/stdc++.h> #define LL long long using namespace std; int read() { int x=0,f=1;char s=getchar(); while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} return x*f; } map<LL,LL>ma; LL quick(LL a,LL x,LL p) { LL ans=1; while(x) { if(x&1) ans=ans*a%p; a=a*a%p;x>>=1; } return ans%p; } void exgcd(LL a,LL b,LL &x,LL &y) { if(!b){x=1,y=0;return;} exgcd(b,a%b,x,y); LL t=x; x=y;y=t-(a/b)*y; } LL inv(LL a,LL b) { LL x,y; exgcd(a,b,x,y); return (x%b+b)%b; } LL fac(LL n,LL x,LL p) { if(!n) return 1; LL ans=1; for(LL i=1;i<=p;++i) if(i%x)ans=ans*i%p;//不含因子x ans=quick(ans,n/p,p);//有循环节,所以乘积用快速幂计算即可(整块的) for(LL i=1;i<=n%p;i++)//未构成整块的 if(i%x) ans=ans*i%p; return ans*fac(n/x,x,p)%p;//当前的不含因子x的乘积乘以递归下去求的剩余阶乘部分的结果 } LL cal(LL n,LL m,LL x,LL p)//x是当前质数,p是题目要求质数 { LL N=fac(n,x,p),M=fac(m,x,p),Z=fac(n-m,x,p); //计算出对于每一个质数的若干次方取模后的结果 LL cnt=0; for(LL i=n;i;i/=x) cnt+=i/x; for(LL i=m;i;i/=x) cnt-=i/x; for(LL i=n-m;i;i/=x) cnt-=i/x; LL ans=quick(x,cnt,p)*N%p*inv(M,p)%p*inv(Z,p)%p; return ans%p; } LL CRT(LL a,LL p,LL x) { return inv(p/x,x)*(p/x)%p*a%p; } void exlucas(LL n,LL m,LL p) { LL t=p,ans=0; for(LL i=2;i*i<=p;++i) { LL k=1; if(t%i)continue; while(t%i==0){k=k*i;t=t/i;}//质因子 ans=(ans+CRT(cal(n,m,i,k),p,k))%p;//对于每一个质因子分别求出结果,再CRT合并 } if(t>1)ans=(ans+CRT(cal(n,m,t,t),p,t))%p; printf("%lld\n",ans%p); } LL gcd(LL a,LL b) { if(b==0)return a; return gcd(b,a%b); } //a=b(mod p) ---> a/c=b/c(mod p/c) void exbsgs(LL A,LL B,LL C) { ma.clear(); if(B==1){printf("0\n"); return;} int k=0;LL tmp=1; while(1) { LL d=gcd(A,C); if(d==1)break; if(B%d) printf("Math Error\n");return; B/=d;C/=d; tmp=tmp*(A/d)%C;//注意A不要像B,C那样除d,因为求的是A^x k++; if(tmp==B){printf("%d\n",k);return;}//因为小于了k的判不到,在这里判 } LL m=sqrt(C)+1; tmp=B; for(int i=0;i<m;++i) { ma[tmp]=i; tmp=tmp*A%C; } LL t=quick(A,m,C); tmp=1; for(int i=1;i<=m;++i) { tmp=tmp*t%C; if(ma.count(tmp)) {printf("%lld\n",i*m-ma[tmp]+k);return; } //记得加上k } printf("Math Error\n");return; } int main() { int T=read(); while(T--) { int op=read();LL y=read(),z=read(),p=read(); if(op==1)printf("%lld\n",quick(y,z,p)); if(op==2)//exbsgs(y,z,p); { ma.clear(); long long aa,b; int pd=0; //scanf("%lld%lld%lld",&aa,&b,&p); aa=y,b=z; if(b==1) { printf("0\n"); pd=1; } if(pd==1) continue; long long d=gcd(aa,p),t=1,k=0; while(d!=1) { if(b%d) { printf("Math Error\n"); pd=1; break; } ++k; b/=d; p/=d; t=(t*(aa/d))%p; if(b==t) { printf("%lld\n",k); pd=1; break; } d=gcd(aa,p); } if(pd==1) continue; long long m=ceil(sqrt(p)),ans; for(int j=0;j<=m;++j) { if(j==0) { ans=b%p; ma[ans]=j; continue; } ans=(ans*aa)%p; ma[ans]=j; } long long x=quick(aa,m,p); ans=t; for(int i=1;i<=m;++i) { ans=(ans*x)%p; if(ma[ans]) { x=i*m-ma[ans]; printf("%lld\n",x+k); pd=1; break; } } if(!pd) printf("Math Error\n"); } if(op==3) { exlucas(z,y,p); } } }