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,如果a的p次方对p取余等于a并且p不是素数,输出yes,否则输出no。
解题思路:因为P比较大暴力的话肯定不行,这里用到了快速幂的算法和同余定理。
快速幂算法:可以把b按二进制展开为:b = p(n)*2^n + p(n-1)*2^(n-1) +…+ p(1)*2 + p(0)
其中p(i) (0<=i<=n)为 0 或 1
这样 a^b = a^ (p(n)*2^n + p(n-1)*2^(n-1) +...+ p(1)*2 + p(0))
= a^(p(n)*2^n) * a^(p(n-1)*2^(n-1)) *...* a^(p(1)*2) * a^p(0)
对于p(i)=0的情况, a^(p(i) * 2^(i-1) ) = a^0 = 1,不用处理
我们要考虑的仅仅是p(i)=1的情况
化简:a^(2^i) = a^(2^(i-1) * 2) = ( a^( p(i) * 2^(i-1) ) )^2。
同余定理:a*b%c=((a%c)*b)%c。
#include
#include
using namespace std;
int isprime(long n){
int i;
for(i=2;i*i
=n){
return 1;
}
else{
return 0;
}
}
int quickpow(long long n,long long m,long long mod)
{
long long ans=1,base=n;
while(m)
{
if(m&1)
{
ans=(base*ans)%mod;
}
base=(base*base)%mod;
m/=2;
}
return ans;
}
int main(){
long long p,a,mod;
while(scanf("%lld %lld",&p,&a)&&p||a){
if(isprime(p)==0&&quickpow(a,p,p)==a){
printf("yes\n");
}
else{
printf("no\n");
}
}
}
本文介绍了一种快速判断特定数值是否为基于a的伪素数的方法,利用快速幂算法和同余定理,有效地解决了POJ3641题目中的问题。
253

被折叠的 条评论
为什么被折叠?



