一、算法进阶给的板子:
int bsgs(int a,int b,int p)
{
map<int,int>_hash;
_hash.clear();
b%=p;
int t=(int) sqrt(p)+1;
for(int j=0;j<t;j++)
{
int val=(ll) b*power(a,j,p)%p;
_hash[val]=j;
}
a=power(a,t,p);
if(a==0) return b==0?1:-1;
for(int i=0;i<=t;i++)
{
int val=power(a,i,p);
int j=_hash.find(val)==_hash.end()?-1:_hash[val];
if(j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}
二、
Discrete Logging POJ - 2417
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#define ll long long
using namespace std;
ll a,b,p;
ll mypow(ll a,ll b,ll p)
{
ll ans=1;
while(b)
{
if(b&1) ans=(ans*a)%p;
a=(a*a)%p;
b>>=1;
}
return ans%p;
}
ll bsgs(ll a,ll b,ll p)
{
a%=p,b%=p;
if(b==1) return 0;
if(b==0&a==0) return 1;
if(!a) return -1;
map<ll,ll>_hash;
map<ll,bool>ha;
ll t=(ll) ceil(sqrt(p*1.0));
for(ll j=0;j<t;j++)
{
ll val=(b*mypow(a,j,p))%p;
{
ha[val]=true;
_hash[val]=j;
}
}
a=mypow(a,t,p);
for(int i=1;i<=t;i++)
{
ll val=mypow(a,i,p);
ll j=-1;
if(ha[val]) j=_hash[val];
//cout<<"i:t:j: "<<i<<t<<j<<endl;
if(j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}
int main(void)
{
while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
{
ll k=bsgs(a,b,p);
if(k==-1)
{
printf("no solution\n");
}
else printf("%lld\n",k);
}
return 0;
}
算法进阶:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<string>
#include<map>
#define ll long long
using namespace std;
ll a,b,p;
ll mypow(ll a,ll b,ll p)
{
ll ans=1;
while(b)
{
if(b&1) ans=(ans*a)%p;
a=(a*a)%p;
b>>=1;
}
return ans%p;
}
ll bsgs(ll a,ll b,ll p)
{
map<ll,ll>_hash;
map<ll,bool>ha;
_hash.clear();
b%=p;
ll t=(ll) sqrt(p+0.5);
//cout<<"t:"<<t<<endl;
for(ll j=0;j<t;j++)
{
ll val=(b*mypow(a,j,p))%p;
if(!ha[val])
{
ha[val]=true;
_hash[val]=j;
}
}
a=mypow(a,t,p);
if(a==0) return b==0?1:-1;
for(int i=0;i<=t;i++)
{
ll val=mypow(a,i,p);
ll j=-1;
if(ha[val]) j=_hash[val];
if(j>=0&&i*t-j>=0) return i*t-j;
}
return -1;
}
int main(void)
{
while(scanf("%lld%lld%lld",&p,&a,&b)!=EOF)
{
ll k=bsgs(a,b,p);
if(k==-1)
{
printf("no solution\n");
}
else printf("%lld\n",k);
}
return 0;
}
三、洛谷
P4195 【模板】exBSGS/Spoj3105 Mod
一直T。。。可能得手写hash吧。
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<string>
#include<cmath>
#include<map>
#include<unordered_map>
#define ll long long
using namespace std;
ll a,b,p;
ll gcd(ll a,ll b)
{
if(b==0) return a;
else return gcd(b,a%b);
}
void exgcd(ll a,ll b,ll &x,ll &y)
{
if(b==0)
{
x=1,y=0;
return ;
}
exgcd(b,a%b,x,y);
ll z=x;
x=y;
y=z-a/b*y;
return ;
}
ll bsgs(ll a,ll b,ll p)
{
a%=p,b%=p;
if(b==1) return 0;
if(b==0&&a==0) return 1;
if(!a) return -1;
if(!b)
{
int ret=0,d;
while((d=gcd(a,p))!=1)
{
ret++;
p/=d;
if(p==1) return ret;
}
return -1;
}
ll k=0,temp=1,d;
while(true)
{
d=gcd(a,p);
if(d==1) break;
if(b%d) return -1;
b/=d;
p/=d;
temp=temp*(a/d)%p;
k++;
if(temp==b) return k;
}
ll x,y;
exgcd(temp,p,x,y);
x=(x%p+p)%p;
b=b*x%p;
//cout<<a<<" "<<b<<" "<<p<<endl;
ll m=ceil(sqrt(p*1.0));
ll e=1;
b%=p;
unordered_map<int,int>ha;
ha[1]=0;
for(int i=1;i<m;i++)
{
e=e*a%p;
if(ha.find(e)==ha.end())
{
ha[e]=i;
}
}
e=e*a%p;
ll inv;
exgcd(e,p,x,y);
inv=(x%p+p)%p;
for(int i=0;i<m;i++)
{
if(ha.find(b)!=ha.end())
{
return i*m+ha[b]+k;
}
b=b*inv%p;
}
return -1;
}
int main(void)
{
while(scanf("%lld%lld%lld",&a,&p,&b),a||b||p)
{
ll k=bsgs(a,b,p);
if(k==-1) printf("No Solution\n");
else printf("%lld\n",k);
}
return 0;
}