挑战程序设计解题报告 2.6.3快速幂运算
1.POJ 3641
题意介绍了一种理论即费马小定理,费马小定理指出若p是一个素数,那么对于任意的整数a(a > 1),都有ap =a (mod p),通俗的讲就是a的p次方对p取余结果是a,这道题问的是费马小定理的逆定理,但是逆定理不一定成立,有少部分数据,不是一个素数,但是满足ap =a (mod p),称这些数字为基于a的伪素数,实际上这个思想也是米勒罗宾大素数检测的核心思想,那么这道题的思路就很简单了,先判断p是不是素数,然后计算快速幂取模。可以说是一道裸的模板题。
代码如下:
template<typename T>
T pow_mod(T x, T n, T mod)
{
T res = 1;
while(n > 0)
{
if(n & 1)
res = res * x % mod; //这里并不通用,如果res * x的值过大,还要使用mul_mod计算(a * b) % mod。
x = x * x % mod;
n >>= 1;
}
return res;
}
bool prime(int p)
{
int k = (int)sqrt(p) + 1;
for(int i = 2; i <= k; ++i)
if(p % i == 0)
return false;
return true;
}
int main()
{
#ifdef LOCAL
///freopen("in.txt", "r", stdin);
///freopen("out.txt", "w", stdout);
#endif // LOCAL
LL a, p;
while(cin >> p >> a)
{
if(!a && !p)
break;
if(!prime(p) && pow_mod(a, p, p) == a)
cout << "yes" << endl;
else
cout << "no" << endl;
}
return 0;
}
2.POJ 1995
这道题的也是裸的模板题,意思就是求(A1B1+A2B2+ ... +AHBH)mod M 实际上根据公式(A + B ) % C == (A % C + B % C) % C,把上式转换为许多个快速幂取模,最后对再来一次求模即可。
代码如下:
LL pow_mod(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()
{
#ifdef LOCAL
///freopen("in.txt", "r", stdin);
///freopen("out.txt", "w", stdout);
#endif // LOCAL
int k;
cin >> k;
while(k--)
{
LL mod;
LL ans = 0;
int n;
int a, b;
cin >> mod;
cin >> n;
while(n--)
{
cin >> a >> b;
ans += pow_mod(a, b, mod);
}
cout << ans % mod << endl;
}
return 0;
}