题目链接:http://poj.org/problem?id=1845
题目:
分析:
此题首先,求约数和,所以可以想到求约数和的方法(p1^0 + p1 ^ 1 + p1 ^ 2..... + p1 ^ x1) * (p2^0 + p2 ^ 1 + p2 ^ 2..... + p2 ^ x2) ....
所以首先将A的质因数 以及 其指数求解出来。
p1 ^ x1 + p2 ^ x2 + p3 ^ x3.....
然后它求的是A ^ B, 所以实际上是 p1 ^ (B * x1) * p2 ^(B * x2) .....
所以求约数和变为了 (p1^0 + p1 ^ 1 + p1 ^ 2..... + p1 ^ (x1 *B)) * (p2^0 + p2 ^ 1 + p2 ^ 2..... + p2 ^( x2*B ) )....
而这个之中乘法的每一项都可以看作是一个等比数列。直接按照等比数列的公式求出每一项即可。
最后每一项都得到这么一个公式
其中 p1 ^ (B *c + 1)则可以直接使用快速幂的方法进行求解。
而p1 - 1的情况,
由于我们mod 的值为9901,是一个质数, 所以 / (p1 - 1)可以使用求逆元的方法得到结果。
但是逆元的话,前提条件是 p1 -1 与 mod的值互质。 而mod为质数,只有p1 - 1 不是 mod 的倍数的时候,才能用快速幂求解逆元(因为mod 也为质数)。
而如果p1 - 1 与 mod 不互质的话呢?
这个时候请看原先的公式,
(p1 ^ x0 + p1 ^ x1 + p2 ^ x2....) % (mo0d),
那么结果实际上就是 (1 + 1 + 1 + .... 1)% mod 也就是 (B * c + 1) % mod.
所以,此题,求出质因数和指数后,准备求乘积是,先判断p - 1 是否与 mod 互质, 按照两种情况分别来求即可。
代码实现:
# include <iostream>
# include <cmath>
using namespace std;
const int mod = 9901;
int qmi(int a , long long b , int mod) // 不会爆longlong所以不需要使用快速乘
{
int res = 1;
while(b)
{
if(b & 1)
{
res = (long long)res * a % mod;
}
b >>= 1;
a = (long long)a * a % mod;
}
return res;
}
int main()
{
int a,b;
scanf("%d %d",&a,&b);
int ans = 1; // 答案
// 筛出a的质因数出来
for(int i = 2 ; i <= a / i ; i++)
{
if(a % i == 0)
{
int res = 0;
while(a % i == 0)
{
res ++;
a /= i;
}
// 质数为i i ,
// 指数为 res * b , 但是要注意 res * b 可能会爆int
long long temp = (long long)res * b;
if(( i - 1 ) % mod == 0)
{
ans = ( (temp + 1) ) % mod * (long long)ans % mod ; // 防止temp + 1 很大,乘以一个ans后爆long long
}
else
{
// 先求 i - 1的逆元
int temp1 = qmi(i - 1, mod - 2 , mod);
// 再求 q ^ (b * c1 + 1)次方
int temp2 = ( qmi(i,temp + 1,mod) - 1 + mod) % mod;
ans = ( ( (long long)ans * temp2 % mod) * (long long)temp1) % mod;
}
}
}
if(a > 1)
{
// a为质数
// b为指数
long long temp = (long long)1 * b;
if(( a - 1 ) % mod == 0)
{
ans = ( (temp + 1) ) % mod * (long long)ans % mod ; // 防止temp + 1 很大,乘以一个ans后爆long long
}
else
{
// 先求 a - 1的逆元
int temp1 = qmi(a - 1, mod - 2 , mod);
// 再求 a ^ (b + 1)次方
int temp2 = ( qmi(a,temp + 1,mod) - 1 + mod) % mod;
ans = ( ( (long long)ans * temp2 % mod) * (long long)temp1) % mod;
}
}
printf("%d\n",ans);
return 0;
}