现在的位置: 首页 > 综合 > 正文

(离散对数与原根) HDU3930(离散对数与原根)

2017年11月04日 ⁄ 综合 ⁄ 共 3420字 ⁄ 字号 评论关闭
 

HDU3930(离散对数与原根)

分类: 数论 177人阅读 评论(0) 收藏 举报

题目:Broot


题意:给出k,m,newx的值,求方程x^k(mod m)=newx的解,其中m为素数。


解法步骤:

(1)先暴力求m的原根g

(2)大步小步求g^t1(mod m)=newx

(3)则g^(t1+n*t2)(mod m)=newx,t2=m-1

(4)x=g^y(mod m),x^k=(g^y)^k=g^(yk)=g^(t1+n*t2)

那么就是求同于方程yk=t1(mod t2),求出y之后带入x=g^y(mod m)解出x


  1. #include <iostream>  
  2. #include <string.h>  
  3. #include <algorithm>  
  4. #include <stdio.h>  
  5. #include <math.h>  
  6. #include <map>  
  7.   
  8. using namespace std;  
  9. typedef long long LL;  
  10.   
  11. const int N=1000005;  
  12.   
  13. int p[N];  
  14. bool prime[N];  
  15. int num,cnt;  
  16. LL k,m,newx,g;  
  17. LL a[65],b[65];  
  18.   
  19. void isprime()  
  20. {  
  21.     num=0;  
  22.     int i,j;  
  23.     memset(prime,true,sizeof(prime));  
  24.     for(i=2;i<N;i++)  
  25.     {  
  26.         if(prime[i])  
  27.         {  
  28.             p[num++]=i;  
  29.             for(j=i+i;j<N;j+=i)  
  30.             {  
  31.                 prime[j]=false;  
  32.             }  
  33.         }  
  34.     }  
  35. }  
  36.   
  37. LL multi(LL a,LL b,LL m)  
  38. {  
  39.     LL ans=0;  
  40.     while(b)  
  41.     {  
  42.         if(b&1)  
  43.         {  
  44.             ans=(ans+a)%m;  
  45.             b--;  
  46.         }  
  47.         b>>=1;  
  48.         a=(a+a)%m;  
  49.     }  
  50.     return ans;  
  51. }  
  52.   
  53. LL quick_mod(LL a,LL b,LL m)  
  54. {  
  55.     LL ans=1;  
  56.     a%=m;  
  57.     while(b)  
  58.     {  
  59.         if(b&1)  
  60.         {  
  61.             ans=multi(ans,a,m);  
  62.             b--;  
  63.         }  
  64.         b>>=1;  
  65.         a=multi(a,a,m);  
  66.     }  
  67.     return ans;  
  68. }  
  69.   
  70. void factor(LL n)  
  71. {  
  72.     cnt=0;  
  73.     for(int i=0;(LL)p[i]*p[i]<=n;i++)  
  74.     {  
  75.         if(n%p[i]==0)  
  76.         {  
  77.             a[cnt]=p[i];  
  78.             int c=0;  
  79.             while(n%p[i]==0)  
  80.             {  
  81.                 c++;  
  82.                 n/=p[i];  
  83.             }  
  84.             b[cnt++]=c;  
  85.         }  
  86.     }  
  87.     if(n>1)  
  88.     {  
  89.         a[cnt]=n;  
  90.         b[cnt++]=1;  
  91.     }  
  92. }  
  93.   
  94. LL extend_Euclid(LL a,LL b,LL &x,LL &y)  
  95. {  
  96.     if(b==0)  
  97.     {  
  98.         x=1;  
  99.         y=0;  
  100.         return a;  
  101.     }  
  102.     LL gd=extend_Euclid(b,a%b,x,y);  
  103.     LL temp=x;  
  104.     x=y;  
  105.     y=temp-(a/b)*y;  
  106.     return gd;  
  107. }  
  108.   
  109. LL Inv(LL n,LL p)  
  110. {  
  111.     return quick_mod(n,p-2,p);  
  112. }  
  113.   
  114. bool dfs(int dept,LL t)  
  115. {  
  116.     if(dept==cnt)  
  117.     {  
  118.         LL ans=quick_mod(g,t,m);  
  119.         if(ans==1&&t!=m-1) return false;  
  120.         return true;  
  121.     }  
  122.     LL tmp=1;  
  123.     for(int i=0;i<=b[dept];i++)  
  124.     {  
  125.         if(!dfs(dept+1,t*tmp)) return false;  
  126.         tmp*=a[dept];  
  127.     }  
  128.     return true;  
  129. }  
  130.   
  131. void find()  
  132. {  
  133.     factor(m-1);  
  134.     for(g=2;;g++)  
  135.         if(dfs(0,1)) break;  
  136. }  
  137.   
  138. LL log_x(LL a,LL b,LL p)  
  139. {  
  140.     map<LL,int>x;  
  141.     LL z=(LL)ceil(sqrt(p*1.0));  
  142.     LL v=Inv(quick_mod(a,z,p),p);  
  143.     LL e=1;  
  144.     x[1]=0;  
  145.     for(int i=1;i<z;i++)  
  146.     {  
  147.         e=multi(e,a,p);  
  148.         if(!x.count(e))  
  149.             x[e]=i;  
  150.     }  
  151.     for(int i=0;i<z;i++)  
  152.     {  
  153.         if(x.count(b))  
  154.             return i*z+x[b];  
  155.         b=multi(b,v,p);  
  156.     }  
  157.     return -1;  
  158. }  
  159.   
  160. LL sol[1005];  
  161.   
  162. void Solve(LL a,LL b,LL n)  
  163. {  
  164.     LL d,x,y;  
  165.     d=extend_Euclid(a,n,x,y);  
  166.     if(b%d) puts("-1");  
  167.     else  
  168.     {  
  169.         n/=d;b/=d;  
  170.         sol[0]=(x*b%n+n)%n;  
  171.         for(int i=1;i<d;i++)  
  172.             sol[i]=sol[i-1]+n;  
  173.         for(int i=0;i<d;i++)  
  174.             sol[i]=quick_mod(g,sol[i],m);  
  175.         sort(sol,sol+d);  
  176.         for(int i=0;i<d;i++)  
  177.             cout<<sol[i]<<endl;  
  178.     }  
  179. }  
  180.   
  181. int main()  
  182. {  
  183.     int t=1;  
  184.     isprime();  
  185.     while(cin>>k>>m>>newx)  
  186.     {  
  187.         find();  
  188.         LL t1=log_x(g,newx,m);  
  189.         LL t2=m-1;  
  190.         cout<<"case"<<t++<<":"<<endl;  
  191.         Solve(k,t1,t2);  
  192.     }  
  193.     return 0;  
  194. }  

抱歉!评论已关闭.