Miller-Rabin算法 codevs 1702 素数判定 2

Posted tech-chen

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Miller-Rabin算法 codevs 1702 素数判定 2相关的知识,希望对你有一定的参考价值。

转载自:http://www.dxmtb.com/blog/miller-rabbin/

普通的素数测试我们有O(√ n)的试除算法。事实上,我们有O(slog³n)的算法。

定理一:假如p是质数,且(a,p)=1,那么a^(p-1)≡1(mod p)。即假如p是质数,且a,p互质,那么a的(p-1)次方除以p的余数恒等于1。(费马小定理)

该定理的逆命题是不一定成立的,但是令人可喜的是大多数情况是成立的。

于是我们就得到了一个定理的直接应用,对于待验证的数p,我们不断取a∈[1,p-1]且a∈Z,验证a^(p-1) mod p是否等于1,不是则p果断不是素数,共取s次。其中a^(p-1) mod p可以通过把p-1写成二进制,由(a*b)mod c=(a mod c)*b mod c,可以在t=log(p-1)的时间内计算出解,如考虑整数相乘的复杂度,则一次计算的总复杂度为log³(p-1)。这个方法叫快速幂取模。

为了提高算法的准确性,我们又有一个可以利用的定理。
定理二:对于0<x<p,x^2 mod p =1 => x=1或p-1。

我们令p-1=(2^t)*u,即p-1为u二进制表示后面跟t个0。我们先计算出x[0]=a^u mod p ,再平方t次并在每一次模p,每一次的结果记为x[i],最后也可以计算出a^(p-1) mod p。若发现x[i]=1而x[i-1]不等于1也不等于p-1,则发现p果断不是素数。

可以证明,使用以上两个定理以后,检验s次出错的概率至多为2^(-s),所以这个算法是很可靠的。

需要注意的是,为了防止溢出(特别大的数据),a*b mod c 也应用类似快速幂取模的方法计算。当然,数据不是很大就可以免了

 

codevs 1702 素数判定 2

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 钻石 Diamond
 
题目描述 Description

一个数,他是素数么?

设他为P满足(P<=2^63-1)

 

输入描述 Input Description

P

输出描述 Output Description

Yes|No

样例输入 Sample Input

2

 

样例输出 Sample Output

Yes

 

数据范围及提示 Data Size & Hint

算法导论——数论那一节
注意Carmichael Number

分类标签 Tags 点此展开 

 素数判定 数论
 
解析:因为数据范围是2^63-1很大,一般方法时间复杂度很高,所以用随机化算法--Miller Rabin算法
 1 /*我唯一想说的就是,这个题目数据错了*/
 2 #define S 15
 3 #include<iostream>
 4 using namespace std;
 5 #include<cstdio>
 6 #define ll long long
 7 #include<cstdlib>
 8 #include<ctime>
 9 ll quick_mod(ll x,ll u,ll n)
10 {
11     x%=n;
12     ll ans=1;
13     while(u)
14     {
15         if(u&1)
16         {
17             u--;
18             ans=(ans*x)%n;
19         }
20         u>>=1;
21         x=(x*x)%n;
22     }
23     return ans;
24 }
25 bool miller_rabin(ll n)
26 {
27     if(n==2) return true;
28     if(n==1||!(n&1)) return false;
29     ll u=n-1;
30     ll t=0;
31     while(!(u&1))
32     {
33         t++;
34         u>>=1;
35     }
36     for(int i=0;i<S;++i)
37     {/*这里可以随机找出x,也可以手打一张表,int ss[7]={2,3,5,7,11,13,17};事实证明这个表在long long范围内都是正确的*/
38         ll x=rand()%(n-1)+1;
39         x=quick_mod(x,u,n);
40         for(int i=1;i<=t;++i)
41         {
42             ll y=quick_mod(x,2,n);
43             if(y==1&&x!=1&&x!=n-1)
44               return false;
45             x=y;
46         }
47         if(x!=1)
48           return false;
49     }
50     return true;
51 }
52 int main()
53 {
54     srand(time(0));
55     ll n;
56     cin>>n;
57     if(miller_rabin(n))
58        printf("Yes");
59     else printf("No");
60     return 0;
61 }

 

以上是关于Miller-Rabin算法 codevs 1702 素数判定 2的主要内容,如果未能解决你的问题,请参考以下文章

浅谈Miller-Rabin素数检测算法

Miller-Rabin?素数测试算法

Miller-Rabin素性判定算法

Miller-Rabin算法

@总结 - 10@ Miller-Rabin素性测试与Pollard-Rho因数分解

Miller-Rabin素数检测算法