PH算法

 

Pohlig Hellman算法:

 

 1 #include<bits/stdc++.h>
 2 using namespace std; 
 3 #define ll long long
 4 #define ld long double 
 5 const int pr[]={2,3,5,7,11,13,31};
 6 int tot;ll fac[105],M[105],R[105];map<ll,ll>mp,h;
 7 inline ll mul(ll a,ll b,ll p){return (a*b-(ll)((ld)a*b/p)*p+p)%p;}
 8 inline ll ml(ll a,ll b,ll p){ll r=0;for(;b;b>>=1,a=(a+a)%p)if(b&1)r=(r+a)%p;return r;}
 9 inline ll pw(ll a,ll b,ll p){ll r=1;for(;b;b>>=1,a=mul(a,a,p))if(b&1)r=mul(r,a,p);return r;}
10 ll gcd(ll a,ll b){return !b?a:gcd(b,a%b);} 
11 ll exgcd(ll a,ll b,ll&x,ll&y){if(!b){x=1;y=0;return a;}int g=exgcd(b,a%b,y,x);y-=a/b*x;return g;}
12 ll crt(int n,ll*m,ll*r)//x%m_i=r_i
13 {
14     ll M=1,R=0,x,y;
15     for(int i=1;i<=n;i++)M*=m[i];
16     for(int i=1;i<=n;i++)
17     {
18         ll t=M/m[i],d=exgcd(t,m[i],x,y);
19         R=(R+mul(mul(r[i],t,M),(x%m[i]+m[i])%m[i],M))%M;
20     }
21     return (R+M)%M;
22 }
23 inline bool Miller_Rabin(ll n)
24 { 
25     if(n==2||n==3||n==5||n==7||n==11||n==13||n==31)return 1;
26     if(!(n&1))return 0;ll r=n-1;
27     int k=0;while((r&1)==0)r>>=1,k++;
28     for(int i=0;i<7;i++)
29     {
30         ll x=pw(pr[i],r,n),y=mul(x,x,n);
31         for(int i=0;i<k;i++,x=y,y=mul(x,x,n))if(y==1&&x!=1&&x!=n-1)return 0;
32         if(y!=1)return 0;
33     }
34     return 1;
35 }
36 #define Func(x) mul(x,x,n)+1
37 inline ll Pollard_Rho(ll n)
38 {
39     ll x=rand()%n+1,y=Func(x);ll k=1;int tst=0;
40     while(x!=y)
41     {
42         ll t=k;k=mul(k,abs(y-x),n);
43         if(!k){t=gcd(t,n);if(t>1)return t;break;}
44         if(tst==100){tst=0;ll t=gcd(k,n);if(t>1)return t;}
45         x=Func(x);y=Func(Func(y));tst++;
46     }
47     ll t=gcd(k,n);return t>1?t:-1;
48 }
49 void Factorization(ll n)
50 {
51     while(!(n&1)){fac[++tot]=2;mp[2]++;n/=2;}
52     if(n==1)return;else if(Miller_Rabin(n)){fac[++tot]=n;mp[n]++;return;}
53     ll p;do p=Pollard_Rho(n);while(p==-1);Factorization(p);Factorization(n/p); 
54 }
55 ll Ord(ll x,ll a,ll p)
56 {
57     tot=0;mp.clear();Factorization(x);
58     for(int i=1;i<=tot;i++)if(!(x%fac[i])&&pw(a,x/fac[i],p)==1)x/=fac[i];
59     tot=0;mp.clear();Factorization(x);return x;
60 }
61 ll qry(ll b,ll p,ll q){for(int i=0;i<q;i++)if(b==h[i])return i;return -1;}
62 ll Pohlig_Hellman(ll a,ll b,ll p)
63 {
64     ll n=Ord(p-1,a,p);int cc=0;
65     for(auto it:mp)
66     {
67         h.clear();ll q=it.first,e=it.second;
68         ll t=1,c=pw(a,n/q,p),bb=b,ans=0,x=n;
69         for(int i=0;i<q;i++,t=mul(t,c,p))h[i]=t;
70         for(ll i=1,qi=1;i<=e;i++,qi*=q)
71         {
72             x=n/qi/q;ll res=pw(bb,x,p),c;
73             c=qry(res,p,q);if(c==-1)return -1;
74             ll t=c*qi,iv=pw(pw(a,t,p),p-2,p);
75             ans+=t;bb=mul(bb,iv,p);
76         }
77         cc++;M[cc]=pw(q,e,p);R[cc]=ans;
78     }
79     return cc?crt(cc,M,R):-1;
80 } 
81 int main()
82 {
83     int T;scanf("%d",&T);
84     while(T--)
85     {
86         ll p,a,b;scanf("%lld%lld%lld",&p,&a,&b);
87         printf("%lld\n",Pohlig_Hellman(a,b,p));
88     }
89     return 0; 
90 }

 

posted @ 2019-08-30 23:28  alonefight  阅读(229)  评论(0编辑  收藏  举报