POJ 2417/BZOJ 3239(Discrete Logging-BSGS)[Template:数论]

来源:互联网 发布:caeses软件 编辑:程序博客网 时间:2024/05/17 05:19

Discrete Logging
Time Limit: 5000MS Memory Limit: 65536KTotal Submissions: 4236 Accepted: 1948

Description

Given a prime P, 2 <= P < 231, an integer B, 2 <= B < P, and an integer N, 1 <= N < P, compute the discrete logarithm of N, base B, modulo P. That is, find an integer L such that 
    BL == N (mod P)

Input

Read several lines of input, each containing P,B,N separated by a space.

Output

For each line print the logarithm on a separate line. If there are several, print the smallest; if there is none, print "no solution".

Sample Input

5 2 15 2 25 2 35 2 45 3 15 3 25 3 35 3 45 4 15 4 25 4 35 4 412345701 2 11111111111111121 65537 1111111111

Sample Output

013203120no solutionno solution19584351462803587

Hint

The solution to this problem requires a well known result in number theory that is probably expected of you for Putnam but not ACM competitions. It is Fermat's theorem that states 
   B(P-1) == 1 (mod P)

for any prime P and some other (fairly rare) numbers known as base-B pseudoprimes. A rarer subset of the base-B pseudoprimes, known as Carmichael numbers, are pseudoprimes for every base between 2 and P-1. A corollary to Fermat's theorem is that for any m 
   B(-m) == B(P-1-m) (mod P) .

Source

Waterloo Local 2002.01.26


裸的BSGS


b^L=b^k1*b^k2

已知b^k1 hash b^k2 复杂度O(sqrt(F)*hash(F))  hash(F)为哈希的复杂度


#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<functional>#include<iostream>#include<cmath>#include<cctype>#include<ctime>using namespace std;#define For(i,n) for(int i=1;i<=n;i++)#define Fork(i,k,n) for(int i=k;i<=n;i++)#define Rep(i,n) for(int i=0;i<n;i++)#define ForD(i,n) for(int i=n;i;i--)#define RepD(i,n) for(int i=n;i>=0;i--)#define Forp(x) for(int p=pre[x];p;p=next[p])#define Forpiter(x) for(int &p=iter[x];p;p=next[p])  #define Lson (x<<1)#define Rson ((x<<1)+1)#define MEM(a) memset(a,0,sizeof(a));#define MEMI(a) memset(a,127,sizeof(a));#define MEMi(a) memset(a,128,sizeof(a));#define INF (2139062143)#define F (100000007)#define MAXN (1000000)typedef long long ll;ll mul(ll a,ll b){return (a*b)%F;}ll add(ll a,ll b){return (a+b)%F;}ll sub(ll a,ll b){return (a-b+(a-b)/F*F+F)%F;}void upd(ll &a,ll b){a=(a%F+b%F)%F;}char s[]="no solution\n";class Math{public: ll gcd(ll a,ll b){if (!b) return a;return gcd(b,a%b);}  ll abs(ll x){if (x>=0) return x;return -x;} ll exgcd(ll a,ll b,ll &x, ll &y)  {      if (!b) {x=1,y=0;return a;}      ll g=exgcd(b,a%b,x,y);      ll t=x;x=y;y=t-a/b*y;      return g;     }  ll pow2(ll a,int b,ll p)  {      if (b==0) return 1;      if (b==1) return a;      ll c=pow2(a,b/2,p);      c=c*c%p;      if (b&1) c=c*a%p;      return c;  }  ll Modp(ll a,ll b,ll p)  {      ll x,y;      ll g=exgcd(a,p,x,y),d;      if (b%g) {return -1;}      d=b/g;x*=d,y*=d;      x=(x+abs(x)/p*p+p)%p;      return x;  }  int h[MAXN];  ll hnum[MAXN];  int hash(ll x)  {      int i=x%MAXN;      while (h[i]&&hnum[i]!=x) i=(i+1)%MAXN;      hnum[i]=x;    return i;}ll babystep(ll a,ll b,int p)  {  MEM(h) MEM(hnum)int m=sqrt(p);while (m*m<p) m++;      ll res=b,ans=-1;            ll uni=pow2(a,m,p);      if (!uni) if (!b) ans=1;else ans=-1; //特判      else      {                    Rep(i,m+1)          {              int t=hash(res);              h[t]=i+1;              res=(res*a)%p;          }          res=uni;          For(i,m+1)  {              int t=hash(res);              if (h[t]) {ans=i*m-(h[t]-1);break;}else hnum[t]=0;              res=res*uni%p;          }          }  return ans; }  }S;int main(){//freopen("poj2471.in","r",stdin);//freopen(".out","w",stdout);ll p,b,n;while(cin>>p>>b>>n){ll ans=S.babystep(b,n,p);if (ans==-1) cout<<s;else cout<<ans<<endl;}return 0;}



0 0
原创粉丝点击