• 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
    ",Pohlig_Hellman(a,b,p));
    88     }
    89     return 0; 
    90 }
  • 相关阅读:
    C++ 练习02 魔术师发牌问题
    C++ 入门2 类型转换
    C++ 入门1 C++简介
    一个简单计算器的实现
    C++练习01 打印杨辉三角
    数据结构01数据结构基础01
    Lesson_7 作业_1 Driver 和 Car
    Caterl Java寒假基础练习题(一) 循环相加
    Lesson_9 上课笔记 多态
    Lesson_10 作业计算工资
  • 原文地址:https://www.cnblogs.com/alonefight/p/11437581.html
Copyright © 2020-2023  润新知