题目描述非常直接,要求你用快速幂解决第一问,exgcd解决第二问,bsgs解决第三问。
emmmm于是现学bsgs
第二问让求最小整数解好烦啊……
假设我们要求得方程$ax+by=c(mod p)$的最小整数解
令$d=gcd(a,b)$
我们求得一个解$x_0,y_0$使得$ax_0+by_0=d(mod p)$
然后$x_0*frac{c}{d}$为最小整数解。
#include<cstdio> #include<cstdlib> #include<algorithm> #include<cctype> #include<cstring> #include<cmath> #include<map> using namespace std; inline long long read(){ long long num=0,f=1; char ch=getchar(); while(!isdigit(ch)){ if(ch=='-') f=-1; ch=getchar(); } while(isdigit(ch)){ num=num*10+ch-'0'; ch=getchar(); } return num*f; } long long Pow(long long a,long long b,long long c){ long long ret=1; while(b){ if(b&1) ret=(ret*a)%c; a=(a*a)%c; b>>=1; } return ret; } long long exgcd(long long a,long long b,long long &x,long long &y){ if(b==0){ x=1;y=0; return a; } long long tmp=exgcd(b,a%b,x,y); long long ret=x;x=y;y=ret-a/b*y; return tmp; } int main(){ int n=read(),m=read(); while(n--){ int y=read(),z=read(),p=read(); if(m==1) printf("%lld ",Pow(y,z,p)); else if(m==2){ long long x,b; long long now=exgcd(y,p,x,b); if(z%now){ printf("Orz, I cannot find x! "); continue; } x/=now; //exgcd(y/now,p/now,x,b); x=(x+p/now)%(p/now); printf("%lld ",x*(z/now)%(p/now)); } else{ if(y%p==0){ printf("Orz, I cannot find x! "); continue; } map<long long,int>d; long long m=ceil(sqrt(p)); for(int i=0;i<=m;++i) d[Pow(y,i,p)*z%p]=i; long long t=Pow(y,m,p); long long ans=1; bool flag=0; for(int i=1;i<=m;++i){ ans=ans*t%p; if(d.count(ans)){ long long ret=i*m%p-d[ans]%p; printf("%lld ",(ret%p+p)%p); flag=1; break; } } if(flag==0) printf("Orz, I cannot find x! "); } } return 0; }