您的位置:首页 > 其它

POJ 1845 Sumdiv

2014-08-26 15:18 323 查看
题目:
LINK

已知a, b.求a^b所有因子的和. 

首先分解质因子,继而可以得到a^b的质因子分解情况 p1^k1 * p2^k2 * p3^k3 * p4^k4 ...... * pn^kn

求的答案是: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)

 接下来的问题就是如何求等比数列的前n项和了

 1)递归二分求等比数列 1+pi+pi^2+pi^3+...+pi^n

    若n为奇数,一共有偶数项,则:s =  (1 + p + p^2 +...+ p^(n/2)) * (1 + p^(n/2+1)) ;

    若n为偶数,一共有奇数项, 则: s = (1 + p + p^2 +...+ p^(n/2-1)) * (1+p^(n/2+1)) + p^(n/2);

    对于式子的前面的部分 依旧递归求解.

 2) 利用等比数列求和公式, s = a1(1-p^n) / (1 - p); 

  在这里s = (p^n - 1) / (p - 1);  前面的部分可以用快速幂求得,而除法取模需要求逆元.

  对于求逆元,这里无法保证 m = 9901与p-1互质,故无法用费马小定理求得逆元.

  可以利用: a/b mod m = (a mod mb) / b 

1.code

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
typedef __int64 LL;
#define N 60000005
#define MOD 9901
LL a, b;
LL cou[111];
vector<LL > save;
void findfac(LL x)
{
save.clear();
memset(cou, 0, sizeof(cou));
for(LL i = 2; i*i <= x; i++) {
if(x%i) continue;
save.push_back(i);
int id = save.size()-1;
while(x%i == 0) {
x /= i; cou[id] ++;
}
}
if(x != 1) {
save.push_back(x); cou[save.size()-1] ++;
}
}
LL powmod(LL x, LL y, LL mod)
{
LL ret = 1;
while(y) {
if(y&1) ret *= x, ret %= MOD;
y >>= 1;
x *= x, x %= MOD;
}
return ret;
}
LL sol(LL x, LL y)
{
if(y == 0) return 1;
if(y&1) return (sol(x, y/2) * (1+powmod(x, y/2+1, MOD))) % MOD;
return (sol(x, y/2-1) * (1 + powmod(x, y/2+1, MOD)) + powmod(x, y/2 , MOD)) % MOD;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
while(scanf("%I64d%I64d", &a, &b) != EOF) {
if(a == 0) {
printf("0\n"); continue;
}
findfac(a);
LL ans = 1;
for(int i = 0 ; i < save.size(); i++) {
LL g = cou[i];
g *= b;
LL tmp = sol(save[i], g);
ans *= tmp;
ans %= MOD;
}
printf("%I64d\n", ans);
}
return 0;
}2,code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define INF 1000000000
typedef __int64 LL;
#define N 60000005
#define MOD 9901
LL a, b;
LL cou[111];
vector<LL > save;
void findfac(LL x)
{
save.clear();
memset(cou, 0, sizeof(cou));
for(LL i = 2; i*i <= x; i++) {
if(x%i) continue;
save.push_back(i);
int id = save.size()-1;
while(x%i == 0) {
x /= i; cou[id] ++;
}
}
if(x != 1) {
save.push_back(x); cou[save.size()-1] ++;
}
}
LL mul(LL x, LL y, LL mod)
{
LL ret = 0;
while(y) {
if(y&1) {
ret += x; ret %= mod;
}
y >>= 1;
x += x; x %= mod;
}
return ret;
}
LL powmod(LL x, LL y, LL mod)
{
LL ret = 1;
while(y) {
if(y&1) ret = mul(ret, x, mod);
y >>= 1;
x = mul(x, x, mod);
}
return ret;
}
LL sol(LL x, LL y)
{
LL g = MOD*(x - 1);
LL tmp = powmod(x, y, g);
LL ret = ((tmp + g -1) % g) / (x-1);
return ret % MOD;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif // ONLINE_JUDGE
while(scanf("%I64d%I64d", &a, &b) != EOF) {
if(a == 0) {
printf("0\n"); continue;
}
findfac(a);
LL ans = 1;
for(int i = 0 ; i < save.size(); i++) {
LL g = cou[i];
g *= b;
LL tmp = sol(save[i], g+1);
ans *= tmp;
ans %= MOD;
}
printf("%I64d\n", ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: