POJ 3641 Pseudoprime numbers【素数+快速幂】

Pseudoprime numbers
Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 8291   Accepted: 3471

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-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

Source

Waterloo Local Contest, 2007.9.23

题意:

费马定理表述,对所有的素数p,对于任意一个数a ,都必定有ap = a (mod p),也就是ap 和在对p 取模的情况下值是相同的,但是有一些数,被定义为 Pseudoprime numbers

因为他们对于基于某些a 值的情况下,费马定理是成立的,但是这个数本身不是素数,特别的,如果某个非素数对基于很多的a 都的都成立,这个数被定义为 Carmichael Numbers----以上都是在说定义...


然后给出两个数p,a 问p 是不是基于a 的Pseudoprime numbers...


题解:

由题意可知,需要满足两条,才能是Pseudoprime numbers

1,p 不是素数

2,ap = a (mod p)


第一条可以进行素性的测试,第二条可以进行快速幂取模运算


/*
http://blog.csdn.net/liuke19950717
*/
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
typedef long long ll;
bool is_prime(ll n)
{
	if(n%2==0)
	{
		return 0;
	}
	ll tp=sqrt(n*1.0+0.5);
	for(ll i=3;i<tp;i+=2)
	{
		if(n%i==0)
		{
			return 0;
		}
	}
	return 1;
}
ll quick_mod(ll n,ll m,ll mod)
{
	ll ans=1;
	while(m)
	{
		if(m&1)
		{
			ans=n*ans%mod;
		}
		n=n*n%mod;
		m>>=1;
	}
	return ans;
}
bool ok(ll p,ll a)
{
	return quick_mod(a,p,p)==a%p&&!is_prime(p);
}
int main()
{
	ll p,a;
	while(scanf("%lld%lld",&p,&a),p|a)
	{
		if(ok(p,a))
		{
			printf("yes\n");
		}
		else
		{
			printf("no\n");
		}
	} 
	return 0;
}


你可能感兴趣的:(POJ 3641 Pseudoprime numbers【素数+快速幂】)