poj3641Pseudoprime numbers(快速幂+同余定理)

poj3641Pseudoprime numbers

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");
		}
	}
} 

你可能感兴趣的:(poj3641Pseudoprime numbers(快速幂+同余定理))