题目链接
http://poj.org/problem?id=1845
分析
将 A A A 分解质因数为 p 1 c 1 ∗ p 2 c 2 ∗ . . . ∗ p n c n p_1 ^ {c_1} * p_2 ^ {c_2} * ... * p_n ^ {c_n} p1c1∗p2c2∗...∗pncn,
则 A B A ^ B AB 为 p 1 B ∗ c 1 ∗ p 2 B ∗ c 2 ∗ . . . ∗ p n B ∗ c n p_1 ^ {B * c_1} * p_2 ^ {B * c_2} * ... * p_n ^ {B * c_n} p1B∗c1∗p2B∗c2∗...∗pnB∗cn,
其约数之和为 ( 1 + p 1 + p 1 2 + . . . + p 1 B ∗ c 1 ) ∗ ( 1 + p 2 + p 2 2 + . . . + p 2 B ∗ c 2 ) ∗ . . . ∗ ( 1 + p n + p n 2 + . . . + p n B ∗ c n ) (1 + p_1 + p_1 ^ 2 + ... + p_1 ^ {B * c_1}) * (1 + p_2 + p_2 ^ 2 + ... + p_2 ^ {B * c_2}) * ... * (1 + p_n + p_n ^ 2 + ... + p_n ^ {B * c_n}) (1+p1+p12+...+p1B∗c1)∗(1+p2+p22+...+p2B∗c2)∗...∗(1+pn+pn2+...+pnB∗cn),
接下来是如何快速求 1 + p + p 2 + . . . + p c 1 + p + p ^ 2 + ... + p ^ c 1+p+p2+...+pc,显然使用等比数列求和公式是行不通的,可以利用分治思想:
若 c c c 为奇数,则其等于 ( ( 1 + p c + 1 2 ) ∗ ( 1 + p + p 2 + . . . + p c − 1 2 ) ((1 + p ^ {\frac{c + 1}{2}}) * (1 + p + p ^ 2 + ... + p ^ {\frac{c - 1}{2}}) ((1+p2c+1)∗(1+p+p2+...+p2c−1),
若 c c c 为偶数,则其等于 ( 1 + p c 2 ) ∗ ( 1 + p + p 2 + p c 2 − 1 ) + p c (1 + p ^ {\frac{c}{2}}) * (1 + p + p ^ 2 + p ^ {\frac{c}{2} - 1}) + p ^ c (1+p2c)∗(1+p+p2+p2c−1)+pc
AC代码
#include <cstdio>
inline int read() {
int num = 0;
char c = getchar();
while (c < '0' || c > '9') c = getchar();
while (c >= '0' && c <= '9')
num = num * 10 + c - '0', c = getchar();
return num;
}
const int mod = 9901;
inline int qpow(int a, int b) {
int ans = 1, x = a % mod;
while (b) {
if (b & 1) ans = ans * x % mod;
x = x * x % mod, b >>= 1;
}
return ans;
}
inline int sum(int p, int q) {
if (!q) return 1;
if (q & 1) return (1 + qpow(p, q / 2 + 1)) * sum(p, q / 2) % mod;
else return (sum(p, q - 1) + qpow(p, q)) % mod;
}
int main() {
int a = read(), b = read(), ans = 1;
if (a < 2) printf("%d", a);
else {
for (int i = 2; i * i <= a; ++i)
if (a % i == 0) {
int cnt = 0;
while (a % i == 0) a /= i, ++cnt;
ans = ans * sum(i, cnt * b) % mod;
}
if (a > 1) ans = ans * sum(a, b) % mod;
printf("%d", ans);
}
return 0;
}