【POJ2417】baby step giant step

  最近在学习数论,然而发现之前学的baby step giant step又忘了,于是去翻了翻以前的代码,又复习了一下。

  觉得总是忘记是因为没有彻底理解啊。

 

  

 

  注意baby step giant step只能用在b和p互质的情况下,因为只有b和p互质的情况下,b才有mod p下的逆元。(下面要用到逆元)

  当b和p不互质,就要处理一下。现在就正在做这么一题,方法以后再写。

 

  

 

  求a^(-m)就用到了求逆元了,那么如何求逆元呢?我学了两种方法:

  ·1:欧拉定理:当a和n互质,a^φ ( n) 1(mod n)。【φ ( n) 是小于等于n的与n互质的数的个数】

  ·2:拓展欧几里德:设a在mod n下的逆元是x,则满足:ax ≡ 1(mod n)

           即ax+ny=1。(a和n是常数,x和y是未知数,用拓展欧几里德求解即可)

 

  注:只有当a和n互质,a才有mod n下的逆元。

 

  代码如下:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<iostream>
 5 #include<algorithm>
 6 #include<cmath>
 7 using namespace std;
 8 #define LL long long
 9 #define Maxn 1000010
10 
11 struct node
12 {
13     int idx;
14     LL val;
15 }baby[Maxn];
16 
17 bool cmp(node x,node y) {return x.val!=y.val ? x.val<y.val : x.idx<y.idx;}
18 
19 int binsearch(int cnt,LL tmp)
20 {
21     int head=0,tail=cnt;
22     while(head<=tail)
23     {
24         int mid=(head+tail)>>1;
25         if(baby[mid].val==tmp) return baby[mid].idx;
26         if(baby[mid].val<tmp) head=mid+1;
27         else tail=mid-1;
28     }
29     return -1;
30 }
31 
32 LL powmod(LL a,LL b,LL mod)
33 {
34     LL ret=1;
35     a%=mod;
36     while(b)
37     {
38         if(b&1) ret=(ret*a)%mod;
39         a=(a*a)%mod;    
40         b>>=1;
41     }
42     return ret;
43 }
44 
45 int main()
46 {
47     LL p,b,n;
48     while(scanf("%lld%lld%lld",&p,&b,&n)!=EOF)
49     {
50         int m=(int)ceil(sqrt((double)(p-1))),cnt=0;
51         baby[0].idx=0,baby[0].val=1;
52         for(int i=1;i<m;i++)
53          baby[i].idx=i,baby[i].val=(baby[i-1].val*b)%p;
54         sort(baby,baby+m,cmp);
55         for(int i=1;i<m;i++)
56           if(baby[i].val!=baby[cnt].val) baby[++cnt]=baby[i];
57         LL bm=powmod(powmod(b,p-2,p),m,p);
58         //printf("bm = %lld\n",bm);
59         int ans=-1;
60         LL tmp=n;
61         for(int i=0;i<m;i++)
62         {
63             int pos=binsearch(cnt,tmp);
64             if(pos!=-1)
65             {
66                 ans=i*m+pos;
67                 break;
68             }
69             tmp=(tmp*bm)%p;
70         }
71         if(ans==-1) printf("no solution\n");
72         else printf("%d\n",ans);
73     }
74     return 0;
75 }
poj2417

 

2016-02-03 09:50:33

 

posted @ 2016-02-03 09:47  konjak魔芋  阅读(383)  评论(0编辑  收藏  举报