【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS
1.快速幂
2.扩展欧几里得(费马小定理)
3.BSGS
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <map> 7 #include <algorithm> 8 using namespace std; 9 10 #define LL long long 11 int T,K; 12 LL a,b,p; 13 14 LL Q_tim(LL x,LL y,LL p){ 15 LL ans=0; 16 while (y){ 17 if (y&1) ans=(ans+x)%p; 18 x=(x+x)%p; 19 y=(y>>1); 20 } 21 return ans; 22 } 23 24 LL Q_pow(LL x,LL y,LL p){ 25 LL ans=1; 26 while (y){ 27 if (y&1) ans=ans*x%p; 28 x=x*x%p; 29 y=(y>>1); 30 } 31 return ans; 32 } 33 34 void ex_gcd(LL a,LL b,LL &x,LL &y,LL &gcd){ 35 if (b==0) {gcd=a;x=1;y=0;return;} 36 ex_gcd(b,a%b,y,x,gcd); 37 y-=x*(a/b); 38 } 39 40 void p2(LL a,LL b,LL p){ 41 LL x,y,gcd,g,ans=p+1; 42 ex_gcd(a,p,x,y,gcd); 43 if (b%gcd!=0){ puts("Orz, I cannot find x!"); return;} 44 ex_gcd(a/gcd,p/gcd,x,y,g); 45 x=x*(b/gcd)%p; 46 x=(x+p)%p; 47 printf("%lld\n",x); 48 } 49 50 void BSGS(LL a,LL b,LL p){ 51 if ((a==0 && b!=0) || (a==1 && b!=1)) { puts("Orz, I cannot find x!"); return;} 52 LL sz=(LL)ceil(sqrt(p)),inv,e=1; 53 map<LL,LL> x; 54 x.clear(); 55 x[1]=0;inv=Q_pow(Q_pow(a,sz,p),p-2,p); 56 for (int i=1;i<sz;i++) {e=Q_tim(e,a,p); if (!x.count(e)) x[e]=i;} 57 for (int i=0;i<sz;i++) { 58 if (x.count(b)) {printf("%lld\n",i*sz+x[b]); return;} 59 b=Q_tim(b,inv,p); 60 } 61 puts("Orz, I cannot find x!"); 62 } 63 64 int main(){ 65 scanf("%d%d",&T,&K); 66 for (int i=1;i<=T;i++){ 67 scanf("%lld%lld%lld",&a,&b,&p); 68 if (K==1) printf("%lld\n",Q_pow(a%p,b,p)); 69 if (K==2) p2(a%p,b%p,p); 70 if (K==3) BSGS(a%p,b%p,p); 71 } 72 return 0; 73 }