Description
Fermat's theorem states that for any prime number p and for any integer a > 1, ap = a (mod p). That is, if we raise a to the pth power and divide by p, the remainder is a. Some (but not very many) non-prime values of p, known as base-a pseudoprimes, have this property for some a. (And some, known as Carmichael Numbers, are base-a pseudoprimes for all a.)
Given 2 < p ≤ 1000000000 and 1 < a < p, determine whether or not p is a base-a pseudoprime.
Input
Input contains several test cases followed by a line containing "0 0". Each test case consists of a line containing p and a.
Output
For each test case, output "yes" if p is a base-a pseudoprime; otherwise output "no".
Sample Input
3 2
10 3
341 2
341 3
1105 2
1105 3
0 0
Sample Output
no
no
yes
no
yes
yes
这道题是判断p是否为一个a-伪素数的题目,可以用Miller测试解决,下面是代码:
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
#include<iostream>
#define ll long long
using namespace std;
ll random(ll n){
return ((ll)(rand())*rand()*rand())%n+1;
}
ll read(){
ll s=0;
char c=getchar();
while(c<'0'||c>'9'){
c=getchar();
}
while(c>='0'&&c<='9'){
s*=10;
s+=c-'0';
c=getchar();
}
return s;
}
ll q(ll a,ll b,ll k){
a%=k;
ll r=a,s=1;
while(b){
if(b&1){
s*=r;
s%=k;
}
r*=r;
r%=k;
b>>=1;
}
return s;
}
bool p(ll a,ll n){
ll m=n-1;
int k=0;
while(!(m&1)){
k++;
m>>=1;
}
ll x=q(a,m,n);
if(x==1||x==n-1){
return 0;
}
while(k--){
x=(x*x)%n;
if(x==n-1){
return 0;
}
}
return 1;
}
bool check(ll n){
int i;
if(n==1||(!(n&1))){
return 0;
}
if(n==2){
return 1;
}
for(i=0;i<10;i++){
ll x=random(n-2)+1;
if(p(x,n)){
return 0;
}
}
return 1;
}
int main(){
srand((unsigned)(time(NULL)));
ll p,a;
p=read();
a=read();
while(p||a){
if(check(p)){
printf("no\n");
}
else{
if(q(a,p,p)==a){
printf("yes\n");
}
else{
printf("no\n");
}
}
p=read();
a=read();
}
return 0;
}
注:随机次数越多,错误几率越小。