【bzoj2242】: [SDOI2011]计算器 数论-快速幂-扩展欧几里得-BSGS

【bzoj2242】: [SDOI2011]计算器

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 }
View Code

 

posted @ 2017-03-19 02:23  karl07  阅读(154)  评论(0编辑  收藏  举报