bzoj 2242 [SDOI2011]计算器 快速幂+扩展欧几里得+BSGS
1:快速幂 2:exgcd 3:exbsgs,题里说是素数,但我打的普通bsgs就wa,exbsgs就A了......
(map就是慢).....
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<map> #define LL long long using namespace std; map<long long,int> pp; map<long long,bool> bo; LL a,b,c; int T,opt; LL qp(LL a,LL b){ LL ans=1; while(b){ if(b&1)ans=(ans*a)%c; a=(a*a)%c;b>>=1; }return ans; } LL gcd(LL x,LL y){return y==0?x:gcd(y,x%y);} LL exgcd(LL o,LL p,LL &x,LL &y){ if(p==0){x=1;y=0;return o;} LL gcd=exgcd(p,o%p,x,y); LL t=x; x=y; y=t-(o/p)*x; return gcd; } LL exbsgs(LL a,LL b,LL c){ pp.clear();bo.clear(); LL g,d=1,m,now=1;int num=0; while((g=gcd(a,c))>1){ if(b%g!=0)return -1; b/=g;c/=g;num++; d=(d*(a/g))%c; } //printf("num==%d\n",num); m=ceil(sqrt(c)); for(int i=0;i<m;i++){ if(!bo[now]){bo[now]=1;pp[now]=i;} now=(now*a)%c; } for(int i=0;i<=m;i++){ LL x,y,e=exgcd(d,c,x,y); x=(x*b%c+c)%c; if(bo[x]) return pp[x]+i*m+num; d=(d*now)%c; } return -1; } int main(){ scanf("%d%d",&T,&opt); if(opt==1){ while(T--){ scanf("%lld%lld%lld",&a,&b,&c); printf("%lld\n",qp(a,b)); } } if(opt==2){ while(T--){ scanf("%lld%lld%lld",&a,&b,&c); LL x,y; LL d=exgcd(a,c,x,y); if(b%d!=0){printf("Orz, I cannot find x!\n");continue;} x*=b/d; LL cd=c/d; x=(x%cd+cd)%cd; printf("%lld\n",x); } } if(opt==3){ while(T--){ scanf("%lld%lld%lld",&a,&b,&c); LL ans=exbsgs(a,b,c); if(ans==-1)printf("Orz, I cannot find x!\n"); else printf("%lld\n",ans); } } return 0; }
人生如梦亦如幻 朝如晨露暮如霞。