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;
}
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;
}
相关文章推荐
- POJ 1845Sumdiv(数论)
- poj1845-Sumdiv
- POJ 1845 Sumdiv (快速幂+质因数+约数和公式+同余模)
- poj 1845Sumdiv(唯一分解定理&&约数和公式&&二分求等比数列和&&反复平方法计算p^n幂~~~好多定理啊)
- poj1845——Sumdiv(数论+幂的因子和)
- poj-1845-Sumdiv-数论-快速幂取模+快速分解因式
- POJ 1845 Sumdiv 笔记
- A^B所有因子和(poj1845 Sumdiv)
- POJ1845-Sumdiv大数约数和
- POJ 1845:Sumdiv 快速幂+逆元
- POJ 1845 Sumdiv (快速幂)
- poj 1845 sumdiv
- Sumdiv POJ - 1845 A^B的所有约数之和
- POJ 1845 Sumdiv(高中数学,推公式,分治)
- poj 1845 Sumdiv(同余模公式)
- poj-1845 Sumdiv (逆元+费马小定理+因子和)
- POJ 1845 Sumdiv
- poj1845 Sumdiv
- poj 1845 Sumdiv 数论
- POJ 1845 Sumdiv