POJ3641 Pseudoprime numbers - 朴素素数判断 + 快速幂运算

Pseudoprime numbers

Time Limit: 1000MS   Memory Limit: 65536K
Total Submissions: 14334   Accepted: 6215

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 ( 2 &lt; p 1 0 9 , 1 &lt; a &lt; p ) p,a(2&lt;p≤10^9,1&lt;a&lt;p) ,判断 p p 是否是 b a s e a base-a p s e u d o p r i m e pseudoprime . p p b a s e a base-a p s e u d o p r i m e pseudoprime ,当且仅当 p p 合数 a p = a ( m o d a^p=a(mod p ) p) .

 
 

分析:

由于 p p 最大只会取到 1 0 9 10^9 ,故可以采用朴素的素数判定方法在 O ( p ) O(\sqrt{p}) 的时间复杂度内判断 p p 是否为合数,且我们可以提前利用素数筛得到 1 0 4.5 10^{4.5} 以内的素数,以减少素数判定时考虑的因子个数。随后我们只需要计算 a p a^p ,由于 p p 较大,需要采用快速幂运算,这样可以在 O ( log 2 p ) O(\log_2{p}) 的时间复杂度内计算出 a p a^p m o d mod p p .

 
 
下面贴代码:

#include <cstdio>
#include <cmath>
using namespace std;

typedef long long ll;
const int MAX_N = 32000;

bool ispr[MAX_N];
int primes[MAX_N];
int pcnt;

void getprime(const int N);
bool is_prime(int x);
ll mod_pow(ll x, ll p, ll m);

int main()
{
	getprime(MAX_N);

	int a, p;
	while (~scanf("%d%d", &p, &a) && a && p)
	{
		if (is_prime(p) || mod_pow(a, p, p) != a)
		{
			printf("no\n");
		}
		else
		{
			printf("yes\n");
		}
	}
	return 0;
}

ll mod_pow(ll x, ll p, ll m)
{
	ll res = 1;
	while (p)
	{
		if (p & 1)
		{
			res = res * x % m;
		}
		x = x * x % m;
		p >>= 1;
	}
	return res;
}

void getprime(const int N)
{
	for (int i = 2; i < N; ++i)
	{
		if (!ispr[i])
		{
			primes[pcnt++] = i;
			for (int j = i << 1; j < N; j += i)
			{
				ispr[j] = true;
			}
		}
	}
}

bool is_prime(int x)
{
	int sqx = sqrt((double)x) + 1;
	for (int i = 0; primes[i] < sqx; ++i)
	{
		if (!(x % primes[i]))
		{
			return false;
		}
	}
	return true;
}

原创文章 42 获赞 22 访问量 3047

猜你喜欢

转载自blog.csdn.net/weixin_44327262/article/details/97774601