hdu3930 broot 离散k次根 ,离散对数

本文介绍了一种解决特定形式的同余方程的方法,即求解形如x^k ≡ newx (mod m)的所有可能值x,其中m为素数。文章首先介绍了原根的概念及其性质,并给出了寻找原根的步骤。接着通过离散对数的定义和性质,提出了一种使用babystep算法高效计算离散对数的方法。
摘要由CSDN通过智能技术生成

转载自:http://hi.baidu.com/fhhgoeqlilqrtxr/item/296f2319e11365ff9c778ac5

/* hdu3930 broot 离散k次根 ,离散对数

http://acm.hdu.edu.cn/showproblem.php?pid=3930

类试题:  http://acm.hdu.edu.cn/showproblem.php?pid=3223


 k, m , newx ,(0 <= newx , m ,k <= 1.5*10^15) , m is a prime number.

求出x^k mod m = newx 其中所有 x 的值

预备1. 原根定义 .若 g^phi(m)=1,mod m,当t<phi(m),g^t!=1,mod m,则称g
  是 模m的原根,phi是欧拉函数.
  性质1.若 gcd(g,m)=1,则 g^ phi(m)=1,mod m.
  例1. m=17,phi(m)=16; 2^8=1,mod m.2不是 模m的原根
       3^k!=1, k<16, 3是 模m的原根
  性质2.若 g是 模m的原根,m素数,则
  {1,2,...,m-1} = {g,g^2,...,g^(m-1)}
  即对 任意 i in [1,m-1], 存在j,使 i=g^j, mod m
  例2. m=17,3是 模m的原根
  {g,g^2,...,g^(m-1)}={3,9,10,13,5,15,11,16,14,8,7,4,12,2,6,1}
  一般地,素数 m  的最小原根 g,2<=g<=100
  原根计算.设p1,...,pk是m-1的素因子
  step 1. g=2
  step 2. 若g^((m-1)/pi )!=1,mod m,i=1,2,..,k
           则 g是原根。结束
           否则 g++,转 step 2。
           
预备2. 离散对数定义.若 a^t=b,mod m,则称t是以a为底的b的对数,mod m
    b!=0,mod m.
   可记为 t=loga(a,b,m);
   若果       loga(a,b,m)不存在,记为loga(a,b,m)=-1;
  例3. loga(2,3,17)=-1,即  不存在t使 2^t=3,mod 17
  性质3. 设g是 模m的原根,则对任意b!=0,mod m,loga(g,b,m)存在
      
题目要求我们求出x^k mod m = newx 其中所有 x 的值。因为其中规定了 m
总是素数,所以我们可以很容易的找到一个m的原根g,然后利用

babystep求出 t1使 g^t1 mod m = newx,然后我们能利用同余原理轻易得出若
t2=m-1,g^(t1+n*t2) mod m = newx ,因为 g^(n*t2)=1 mod m

简单地说  ,如果 t1 %k=0, m0=t1/k,t1=m0*k则

  g^t1=g^ (m0*k)= (g^m0)^k=newx,mod m
  x=g^m0 是 x^k mod m = newx的解

一般地说 如果  m0*k = t1, mod t2   // ax=b ,mod m

 则  g^(m0*k)=g^t1 =newx ,mod m

    x=g^m0是一个解

    m0*k = t1, mod t2   (1) ,这是把 m0看做未知数的方程
   
   (1)有解的 条件是 t1% d=0, d=gcd(k,t2)
    
    m0*k/d = t1/d, mod t2/d   (2) ,和(1)等价的方程
   
    m0=inv(k/d) * t1/d

  设 t1%d=0
 计算方法:用扩展Euclid算法 :
    ex_gcd( k, t2, d, x0, y0 );
      x0*k+y0*t2=d
      x0*k/d+y0*t2/d=1
     
      inv(k/d)=x0 ,mod t2/d
    m0 = x0*t1/d,mod t2/d;
    其他 解mi是
    mi=m0+i*(t2/d),i=1,2,...,d-1
    
 
 
求出g^m0,g^m1......g^m(d-1)
一系列数字就是我们要求的答案了。


算法
1. 计算 m的一个原根 g
2. 计算 t1=loga(g,newx,m),即要求 t1使 g^t1=newx,mod m
   根据性质3. t1是存在的,t1 in[1,m-1],计算量是 O(m) ,
   babystep是一种计算量是 O(m^0.5)的方法
   z = ceil( m^0.5);
   则 [1,m-1]中的数可表示为 t1=i*z+j, j<z
  
   g^t1=g^(i*z+j) =  g^(i*z)  * g^j
  
   先计算出 e[j]= g^j,mod m.
   如果 有j<z, e[j]= g^j=newx,mod m,则 t1=j,结束
  
   否则 如果 有j<z,
    e[j]= g^j=newx*inv(g^z),mod m,即
    g^z * g^j =newx,mod m 则 t1=z+j,结束
   ............................
   否则 如果 有j<z,
    e[j]= g^j=newx*inv(g^(i*z)),mod m,即
    g^(i*z) * g^j =newx,mod m 则 t1=i*z+j,结束
3.  算出 t1后,  g^t1=newx,mod m ,设想 g^((t1*x0)*k) =newx,mod m
   x0 =inv(k),则 x= g^(t1*x0),x^k=newx,mod m
   ex_gcd( k, t2, d, x0, y0 );
   if(t1%d!=0) 无解,否则
       m0 = x0*t1/d,mod t2/d;
    其他 解mi是
    mi=m0+i*(t2/d),i=0,1,2,...,d-1
 
   x={g^mi,i=0,i<d}
   
  
  
 

*/


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值