程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> SGU 261 Discrete Roots

SGU 261 Discrete Roots

編輯:C++入門知識

給定p,k,a,其中p,k是素數,求x^k=a (mod p)。 傳說中的much simpler task。。。。   設r是p的原根,(素數都有原根) 那麼r^1,r^2...r^phi(p)構成模p的完全剩余系, 故可設x=r^i ,a=r^j,那麼等式化成 r^(i*k)=r^j (mod p) 那麼由定理可得 i*k=j (mod p-1) 由r^j=a mod p 可由離散對數求得j 由i*k=j mod p-1 可由模線性方程求得i 由x=r^i 求得x 然後對所有x取余後排序,輸出即可。   [cpp]   #include<map>   #include<cstdio>   #include<cmath>   #include<vector>   #include<iostream>   #include<algorithm>   using namespace std;   typedef long long ll;   vector<ll>f,as;   ll pow(ll a,ll b,ll mod){       ll as=1;       while(b){           if(b&1)as=(as*a)%mod;           a=(a*a)%mod;b>>=1;       }       return as;   }   bool g_test(ll g,ll p){       for(ll i=0;i<f.size();i++)           if(pow(g,(p-1)/f[i],p)==1)               return 0;       return 1;   }   ll yuangen(ll p){       f.clear();       ll tmp=p-1;       for(ll i=2;i<=tmp/i;i++)           if(tmp%i==0){               f.push_back(i);               while(tmp%i==0)                   tmp/=i;           }       if(tmp!=1)f.push_back(tmp);       ll g=0;       while(++g)           if(g_test(g,p))               return g;   }   ll discrete_log(ll x,ll n,ll m){//x^y=n (mod m) 求 y       map<ll,int>rec;       ll s=(ll)(sqrt(m)+0.5);       ll cur=1;       for(int i=0;i<s;i++){           rec[cur]=i;           cur=cur*x%m;       }       ll mul=cur;       cur=1;       for(int i=0;i<s;i++){           ll more=n*pow(cur,m-2,m)%m;           if(rec.count(more))return i*s+rec[more];           cur=cur*mul%m;       }       return -1;   }   ll ex_gcd(ll a,ll b,ll& x,ll& y){       if(b==0){           x=1;y=0;           return a;       }       else{           ll r=ex_gcd(b,a%b,y,x);           y-=x*(a/b);           return r;       }   }   void line_mod_equation(ll a,ll b,ll n){//ax=b (mod n) 求x       ll x,y,d;as.clear();       d=ex_gcd(a,n,x,y);       if(b%d==0){           x%=n;x+=n;x%=n;           as.push_back(x*(b/d)%(n/d));           for(ll i=1;i<d;i++)               as.push_back((as[0]+i*n/d)%n);       }   }   int main(){       ll a,k,p,g,q;       while(~scanf("%lld%lld%lld",&p,&k,&a)){           if(a==0){puts("1\n0");continue;}//a==0特判           g=yuangen(p);           q=discrete_log(g,a,p);           line_mod_equation(k,q,p-1);           for(int i=0;i<as.size();i++)               as[i]=pow(g,as[i],p);           sort(as.begin(),as.end());           printf("%d\n",as.size());           for(int i=0;i<as.size();i++)               printf("%lld%c",as[i],i==as.size()-1?'\n':' ');       }       return 0;   }  

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved