POJ 3641 Pseudoprime 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,判断 p 是否为合数且满足 ap ≡ a(mod p)

解题思路:
判断素数+快速幂
注意,由于题目中p的范围过大,因此不能先进行素数筛法来筛选素数

快速幂模板代码:

ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res*x%mod;
		x = x*x%mod;
		n >>= 1;
	}
	return res;
}

AC代码:

#include
#include
using namespace std;
typedef long long ll;
const ll maxn = 1e9 + 5;
bool Prime(ll t) {
	for (ll i = 2; i*i<= t; i++) {
		if (t%i == 0)return false;
	}
	return true;
}

ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res*x%mod;
		x = x*x%mod;
		n >>= 1;
	}
	return res;
}

int main() {
	ll p, a;
	while (scanf("%lld%lld",&p,&a)!=EOF) {
		if (p == 0 && a == 0)break;
		if (Prime(p)) {
			cout << "no" << endl;
			continue;
		}
		ll res = mod_pow(a, p, p);
		if (res == a)cout << "yes" << endl;
		else cout << "no" << endl;
	}
}

你可能感兴趣的:(数论,挑战程序设计)