解方程 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 }