Poj 2417 baby-step 素数

解方程 a^x=b(mod c) c为素数,用算法babystep,水过的,4s多

#include <iostream>

#include <stdio.h>

#include <cmath>

using namespace std;

typedef long long ll;

const ll maxn=65535;

struct Hashh

{

ll a,b,next;

}Hash[maxn<<1];

ll flag[maxn+100];//注意要赋初值0

ll top,idx;//注意要赋初值maxn

void ins(ll a,ll b)

{

ll k=b&maxn;//maxn=11…111,若比maxn大,取前16位,否则与原freopen("in.txt","r",stdin);相等

if(flag[k]!=idx)//第b&maxn个槽为空

{

flag[k]=idx;

Hash[k].a=a;

Hash[k].b=b;

Hash[k].next=-1;

return ;

}

//第b&maxn个槽不为空

while(Hash[k].next!=-1)//到链表的最后一个

{

if(Hash[k].b==b) return;//若b已经存在,返回

k=Hash[k].next;

}

Hash[k].next=++top;

Hash[top].next=-1;

Hash[top].a=a;

Hash[top].b=b;

}

ll find(ll b)

{

ll k=b&maxn;

if(flag[k]!=idx) return -1;//为空

while(k!=-1)

{

if(Hash[k].b==b) return Hash[k].a;

k=Hash[k].next;

}

return -1;

}

ll gcd(ll a,ll b){if(b==0)return a;return gcd(b,a%b);}

ll mulmod(ll a,ll b,ll n)

{

ll ret=0;

a%=n;

while(b>=1)

{

if(b&1)

{

ret+=a;

if(ret>=n) ret-=n;

}

a<<=1;

if(a>=n) a-=n;

b>>=1;

}

return ret;

}

 

ll exmod(ll a,ll b,ll n)

{

ll ret=1;

a%=n;

while(b>=1)

{

if(b&1)

ret=mulmod(ret,a,n);

a=mulmod(a,a,n);

b>>=1;

}

return ret;

}

 

ll exgcd(ll a,ll b,ll &x,ll &y)

{

if(0==b) {x=1;y=0;return a;}

ll d=exgcd(b,a%b,x,y);

ll t=x;x=y;y=t-a/b*y;

return d;

}

 

ll invmod(ll a,ll n)

{

ll x,y;

if(exgcd(a,n,x,y)!=1)return -1;

return (x%n+n)%n;

}

 

ll babystep(ll a,ll b,ll c)

{

top=maxn;idx++;

ll tmp,r=b,w;

ll m=(ll)ceil(sqrt((double)(c-1)));

ins(0,1);

for(ll i=1;i<=m;i++) {ins(i,exmod(a,i,c));}

tmp=invmod(exmod(a,m,c),c);

for(ll i=0;i<=m-1;i++)

{

 

w=find(r);

if(w!=-1){return i*m+w;}

r=(r*tmp%c+c)%c;

}

return -1;

}

int main()

{

ll a,b,c,tmp;

freopen("in.txt","r",stdin);

while(scanf("%lld%lld%lld",&c,&a,&b)!=EOF)

{

b%=c;

 

tmp=babystep(a,b,c);

 

if(tmp<0) printf("no solution\n");

else printf("%lld\n",tmp);

}

return 0;

}

改进了一下,刷到32ms

 1 #include <iostream>
2 #include <stdio.h>
3 #include <cmath>
4 using namespace std;
5 typedef long long ll;
6 const int maxn=65535;
7 struct Hashh
8 {
9 int a,b,next;
10 }Hash[maxn<<1];
11 int flag[maxn+100];//注意要赋初值0
12 int top,idx;//注意要赋初值maxn
13 void ins(int a,int b)
14 {
15 int k=b&maxn;//maxn=11…111,若比maxn大,取前16位,否则与原freopen("in.txt","r",stdin);相等
16 if(flag[k]!=idx)//第b&maxn个槽为空
17 {
18 flag[k]=idx;
19 Hash[k].a=a;
20 Hash[k].b=b;
21 Hash[k].next=-1;
22 return ;
23 }
24 //第b&maxn个槽不为空
25 while(Hash[k].next!=-1)//到链表的最后一个
26 {
27 if(Hash[k].b==b) return;//若b已经存在,返回
28 k=Hash[k].next;
29 }
30 Hash[k].next=++top;
31 Hash[top].next=-1;
32 Hash[top].a=a;
33 Hash[top].b=b;
34 }
35
36 int find(int b)
37 {
38 int k=b&maxn;
39 if(flag[k]!=idx) return -1;//为空
40 while(k!=-1)
41 {
42 if(Hash[k].b==b) return Hash[k].a;
43 k=Hash[k].next;
44 }
45 return -1;
46 }
47
48 int gcd(int a,int b){if(b==0)return a;return gcd(b,a%b);}
49 int exgcd(int a,int b,int &x,int &y)
50 {
51 if(0==b) {x=1;y=0;return a;}
52 int d=exgcd(b,a%b,x,y);
53 int t=x;x=y;y=t-a/b*y;
54 return d;
55 }
56
57 int exmod(ll a,int b,int c)
58 {ll ret=1%c;a%=c;while(b){if(b&1)ret=ret*a%c;a=a*a%c;b>>=1;}return ret;}
59
60 int invmod(int a,int n)
61 {
62 int x,y;
63 if(exgcd(a,n,x,y)!=1)return -1;
64 return (x%n+n)%n;
65 }
66
67 int babystep(int a,int b,int c)
68 {
69 top=maxn;idx++;
70 ll buf=1%c,r=b,tmp;
71 int w,i;
72 int m=(int)ceil(sqrt((double)(c-1)));
73 for(i=0;i<=m;i++) {ins(i,buf);buf=buf*a%c;}
74 tmp=invmod(exmod(a,m,c),c);
75 for(i=0;i<=m-1;i++)
76 {
77 w=find(r);
78 if(w!=-1){return i*m+w;}
79 r=(r*tmp%c+c)%c;
80 }
81
82 return -1;
83 }
84
85
86 int main()
87 {
88 int a,b,c,tmp;
89 freopen("in.txt","r",stdin);
90 while(scanf("%d%d%d",&c,&a,&b)!=EOF)
91 {
92 b%=c;
93 tmp=babystep(a,b,c);
94 if(tmp<0) printf("no solution\n");
95 else printf("%d\n",tmp);
96 }
97 return 0;
98 }



 

posted on 2012-03-19 19:46  Inpeace7  阅读(426)  评论(0编辑  收藏  举报

导航