概述
>Link
ybtoj约数之和
>Description
求 A B A^B AB 所有约数之和模 9901 9901 9901
>解题思路
可以把
A
A
A 质因数分解为
p
1
k
1
∗
p
2
k
2
∗
.
.
.
∗
p
n
k
n
p_1^{k_1}*p_2^{k_2}*...*p_n^{k_n}
p1k1∗p2k2∗...∗pnkn
A
B
A^B
AB 就把这堆乘
B
B
B 次
所有约数就是这些质因数一一组合,那么约数之和就等于
∏
i
=
1
n
∑
j
=
0
k
i
∗
B
p
i
j
prod_{i=1}^{n}sum _{j=0}^{k_i*B}p_i^j
∏i=1n∑j=0ki∗Bpij
根据等比数列公式
S
=
a
1
∗
(
1
−
p
n
)
1
−
p
S=frac{a_1*(1-p^n)}{1-p}
S=1−pa1∗(1−pn),可以把式子转换成
∏
i
=
1
n
1
−
p
i
k
i
∗
B
+
1
1
−
p
i
prod_{i=1}^{n}frac{1-p_i^{k_i*B+1}}{1-p_i}
∏i=1n1−pi1−piki∗B+1,加一是因为还有个
p
i
0
p_i^0
pi0
分子部分用快速幂求,分母部分用扩展欧几里得求逆元
>代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const LL Mod = 9901;
void ex_gcd (LL a, LL b, LL &x, LL &y)
{
if (!b) {x = 1, y = 0; return;}
LL X, Y;
ex_gcd (b, a % b, X, Y);
x = Y;
y = X - (a / b) * Y;
}
LL inv (LL a)
{
LL inv_a, y;
ex_gcd (a, Mod, inv_a, y);
return (inv_a + Mod) % Mod;
}
LL power (LL a, LL b)
{
LL ret = 1;
for (a %= Mod; b; b >>= 1, a = a * a % Mod)
if (b & 1) ret = ret * a % Mod;
return ret;
}
int main()
{
LL a, b, ans, cnt;
scanf ("%lld%lld", &a, &b);
ans = 1;
for (LL i = 2; i <= a; i++)
{
if (!a) break;
if (a % i) continue;
cnt = 0;
while (a % i == 0) a /= i, cnt++;
ans = ans * (power (i, b * cnt + 1) - 1) % Mod;
ans = ans * inv (i - 1) % Mod;
}
printf ("%lld", ans);
return 0;
}
最后
以上就是奋斗鲜花为你收集整理的约数之和【数论】【扩欧】的全部内容,希望文章能够帮你解决约数之和【数论】【扩欧】所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复