POJ-1845 Sumdiv
Description
Consider two natural numbers A and B. Let S be the sum of all natural divisors of A^B. Determine S modulo 9901 (the rest of the division of S by 9901).
Input
The only line contains the two natural numbers A and B, (0 <= A,B <= 50000000)separated by blanks.
Output
The only line of the output will contain S modulo 9901.
Sample Input
2 3
Sample Output
15
Hint
2^3 = 8.
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
The natural divisors of 8 are: 1,2,4,8. Their sum is 15.
15 modulo 9901 is 15 (that should be output).
题目大意:
给你两个数a和b,让你求a的b次方的因子的和。
解题思路:
蒟蒻是从这篇博客(http://blog.csdn.net/lyy289065406/article/details/6648539)里面得到的思路0.0
这篇博客说的很详细,对于数论新手是非常友好的0.0
以及这道题似乎还可以通过逆元求解。不过我还是不会0.0
这道题的思路其实主要来自于两个定理:
1.对于任何整数,都有且只有一种方式能够写出其素因子的乘积形式。
2.对于已经分解的整数A=(p1^k1)*(p2^k2)*(p3^k3)*....*(pn^kn)有A的所有因子之和为S = (1+p1+p1^2+p1^3+...p1^k1) * (1+p2+p2^2+p2^3+….p2^k2) * (1+p3+ p3^3+…+ p3^k3) * .... * (1+pn+pn^2+pn^3+...pn^kn)
根据这两个定理,就可以解出这个题目了。
代码:
#include <cstdio>
#include <cstring>
using namespace std;
#define mod 9901
typedef long long LL;
const int maxn = 1e4 + 5;
LL prime[maxn], f[maxn], g[maxn];
void init(){
memset(prime, 0, sizeof(prime));
for(int i = 2; i < maxn; ++i){
if(!prime[i]) prime[++prime[0]] = i;
for(int j = 1; j <= prime[0] && prime[j] < maxn / i; ++j){
prime[prime[j] * i] = 1;
if(i % prime[j] == 0) break;
}
}
}
LL mod_mul(LL a, LL b){
LL res = 0;
while(b){
if(b & 1) res = (res + a) % mod;
a = (a + a) % mod;
b >>= 1;
}
return res % mod;
}
LL mod_exp(LL a, LL b){
LL res = 1;
while(b){
if(b & 1) res = mod_mul(res, a);
a = mod_mul(a, a);
b >>= 1;
}
return res % mod;
}
LL Cal(LL x, LL num){
if(num == 0) return 1;
if(num == 1) return (1 + x) % mod;
LL res = 1;
if(num % 2 == 0){
res = (res + mod_exp(x, num / 2 + 1)) % mod;
res = (res * Cal(x, num / 2 - 1)) % mod;
res = (res + mod_exp(x, num / 2)) % mod;
}else{
res = (res + mod_exp(x, num / 2 + 1)) % mod;
res = (res * Cal(x, num / 2)) % mod;
}
return res;
}
int main(){
init();
LL a, b, tmp, cnt;
while(~scanf("%lld%lld", &a, &b)){
if(a == 1) {puts("1"); continue;}
tmp = a; cnt = 0;
// memset(f, 0, sizeof(f));
// memset(g, 0, sizeof(g));
for(int i = 1; i <= prime[0]; ++i){
if(tmp % prime[i] == 0){
f[cnt] = prime[i];
g[cnt] = 0;
while(tmp % prime[i] == 0){
tmp /= prime[i];
++g[cnt];
}
++cnt;
}
if(tmp == 1) break;
}
if(tmp != 1){
f[cnt] = tmp; g[cnt++] = 1;
}
LL ans = 1;
for(int i = 0; i < cnt; ++i) {
g[i] *= b;
// printf("f = %lld, g = %lld\n", f[i], g[i]);
ans = (ans * Cal(f[i], g[i])) % mod;
}
printf("%lld\n", ans);
}
return 0;
}

浙公网安备 33010602011771号