Chinaunix首页 | 论坛 | 博客
  • 博客访问: 71515
  • 博文数量: 33
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 220
  • 用 户 组: 普通用户
  • 注册时间: 2014-07-15 22:22
文章分类

全部博文(33)

文章存档

2016年(3)

2015年(23)

2014年(7)

我的朋友

分类: C/C++

2014-11-29 16:29:07

 

Fermat定理n是奇素数,a是任意正整数(1≤ an−1),则 an−1≡1pmod n。[]

Miller-Rabin算法的理论基础 如果n是一个奇素数,将n−1表示成2s*r的形式,r是奇数,an是互素的任何整数,那么ar≡1pmod n或者对某个j(0 ≤ js−1, jZ)等式a2jr≡−1 pmod n成立。[]

这个理论是由Fermat定理推导而来:n是一个奇素数,则方程 x2≡1pmod n只有±1两个解。

定理 3xyn是整数,如果x2 = y2pmod n, 但x≠± ypmod n,则(xy)和n的公约数中有n的非平凡因子。

输入:一个大于3的奇整数n和一个大于等于1的安全参数t(用于确定测试轮数)。

输出:返回n是否是素数(概率意义上的,一般误判概率小于((1/2))80)即可)。

  1. 将n-1表示成2sr

  2. 对i从1到t做循环做以下操作:

    1. 选择一个随机整数a(2 ≤ an−2)

    2. 计算yar bmod n

    3. 如果y≠1并且yn−1循环做下面的操作,否则转3:

      1. j ← 1

      2. js−1并且yn−1循环做下面操作,否则跳到(iv.)

      3. 计算yy2 bmod n,如果y = 1返回“合数”,否则jj + 1

      4. 如果yn−1则返回“合数”

  3. 返回“素数”

其中第(vi.)步是基于定理3得来的。 []

经过独立的t轮Miller-Rabin算法将一个合数误判为素数的可能性不大于4t。这个概率是给予Fermat定理的算法中是最好的。这个误判概率是利用下面的两个定理证明的。

定理 1:d = gcd(k,m)那么在有限群{g1,g + 2,···,gm = 1}中(g是有限群的生成元,m是有限群的阶)有d个元素满足方程xk = 1。

定理 2:p是一个素奇数,p−1 = 2shh是奇数),那么在乘法群(Z/pZ)*中满足方程 x2rt = −1pmod pt是奇数)的元素个数是:0,如果rs;2rgcd(h,t)如果r<s

利用这两个定理,对算法输入n分3种情况讨论:

  1. n是可以被某个素数的平方整除的时候;

  2. n是两个不同的素数的乘积的时候;

  3. n是两个以上不同素数乘积的时候。

这样就可以证明Miiler-Rabin算法的误判概率上界。

Miller-Rabin算法是一个概率算法,算法的计算集中于(b)步和(c)步的循环中,最坏情况是(iv.)的循环没有中途推出,则一轮Miller-Rabin算法的最坏情况复杂度为(1 + O(1))log2(n)(以模n乘法为基本操作)。如果以单精度乘法操作作为时间复杂度的衡量,则一轮优化的Miller-Rabin算法的最坏情况时间复杂度是O(log23(n))。从时间复杂度来看Miller-Rabin算法的性能是很好的。在实际应用中,Miller-Rabin算法的实际执行速度也很快。


代码实现:

点击(此处)折叠或打开

  1. #include <iostream>

  2. using namespace std;

  3. typedef unsigned __int64 llong;

  4. llong mod_pro(llong x,llong y,llong n)
  5. {
  6.     llong ret=0,tmp=x%n;
  7.     while(y)
  8.     {
  9.         if(y&0x1)if((ret+=tmp)>n)ret-=n;
  10.         if((tmp<<=1)>n)tmp-=n;
  11.         y>>=1;
  12.     }
  13.     return ret;
  14. }
  15. llong mod(llong a,llong b,llong c)
  16. {
  17.     llong ret=1;
  18.     while(b)
  19.     {
  20.         if(b&0x1)ret=mod_pro(ret,a,c);
  21.         a=mod_pro(a,a,c);
  22.         b>>=1;
  23.     }
  24.     return ret;
  25. }
  26. llong ran()
  27. {
  28.     llong ret=rand();
  29.     return ret*rand();
  30. }
  31. bool is_prime(llong n,int t)
  32. {
  33.     if(n<2)return false;
  34.     if(n==2)return true;
  35.     if(!(n&0x1))return false;
  36.     llong k=0,m,a,i;
  37.     for(m=n-1;!(m&1);m>>=1,k++);
  38.     while(t--)
  39.     {
  40.         a=mod(ran()%(n-2)+2,m,n);
  41.         if(a!=1)
  42.         {
  43.             for(i=0;i<k&&a!=n-1;i++)
  44.                 a=mod_pro(a,a,n);
  45.             
  46.             if(i>=k)return false;
  47.         }
  48.     }
  49.     return true;
  50. }
  51. int main()
  52. {
  53.     llong n;
  54.     while(scanf("%I64u",&n)!=EOF)
  55.         if(is_prime(n,3))
  56.             cout<<"YES\n";
  57.         else
  58.             cout<<"NO\n";
  59.         return 0;
  60. }


 

阅读(755) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~