用Miller-Rabin算法测试素数
用了两种实现方式
#include<stdio.h>
typedef long long LL;
//计算a*b(mod n)
LL PowerMulti(LL a, LL b, LL n){
LL ans = 0;
while(b){
if(b&1){
ans = (ans+a)%n;
}
b >>= 1;
a = (a*2)%n;
}
return ans;
}
//快速幂,计算a^b(mod n)
LL PowerMod(LL a, LL b, LL n){
LL ans = 1;
while(b){
if(b%2){
ans = PowerMulti(ans, a, n);
}
b /= 2;
a = PowerMulti(a, a, n);
}
return ans;
}
int Miller_Rabin(LL n){
int test[12] = {2,3,5,7,11,13,17,19,23,29,31,37};
LL u = n-1, x;
int i, j, k=0;
while(u%2 == 0){
u /= 2;
k++;
}
for(i = 0; i < 12 && test[i] < n; i++){
x = PowerMod(test[i], u, n);
if(x == 1 || x == n-1){
continue;
}
for(j = 0; j < k-1; j++){
x = PowerMod(x, 2, n);
if(x == 1){
return 0;
}else if(x == n-1){
goto K;
}
}
return 0;
K: ;
}
return 1;
}
int main(){
int t, prime;
LL n;
scanf("%d", &t);
while(t--){
scanf("%lld", &n);
if(n == 2){
prime = 1;
}else if(n%2 == 0){
prime = 0;
}else{
prime = Miller_Rabin(n);
}
if(prime){
printf("Yes\n");
}else{
printf("No\n");
}
}
return 0;
}
hihocoder上给出的提示
int Miller_Rabin(long long n){
long long u = n-1, x, y, a, k;
int i;
while(u%2 == 0){
u /= 2;
}
k = u;
for(i = 0; i < 100; i++){
u = k;
a = rand()%(n-2) + 2;
x = PowerMod(a, u, n);
while(u < n){
y = PowerMod(x, 2, n);
if(y == 1 && x != 1 && x != n-1){
return 0;
}
x = y;
u = u*2;
}
if(x != 1){
return 0;
}
}
return 1;
}
犯了一个小错误,浪费了太多时间,输入unsigned long long 应该用%llu而不是%ull,但是为什么自己测试没问题,编译还能通过