因子和
题目描述
输入两个整数 a a a 和 b b b,求 a b a^b ab 的因子和。
由于结果太大,只要输出它对 9901 9901 9901 取模的结果。
输入格式
仅一行,为两个整数 a a a 和 b b b。
输出格式
输出一行一个整数表示答案对 9901 9901 9901 取模的结果。
样例 #1
样例输入 #1
2 3
样例输出 #1
15
提示
数据规模与约定
对于全部的测试点,保证 1 ≤ a ≤ 5 × 1 0 7 1 \leq a \leq 5 \times 10^7 1≤a≤5×107, 0 ≤ b ≤ 5 × 1 0 7 0 \leq b \leq 5 \times 10^7 0≤b≤5×107。
个人题解
思路
给定 a , b a,b a,b 求 a b a^b ab 这个数所有的因数和,答案对 9901 取模。
思路
由唯一分解定理得任意正整数
Z + = p 1 k 1 ∗ p 2 k 2 ∗ p 3 k 3 ∗ . . . . ∗ p n k n Z^+ = p^{k^1}_1 * p^{k^2}_2 * p^{k^3}_3 * .... * p^{k^n}_n Z+=p1k1∗p2k2∗p3k3∗....∗pnkn
又由唯一分解定理得一个正整数的因数和
s = ( 1 + p 1 1 + p 1 2 + p 1 3 + . . . . + p 1 k 1 ) ∗ ( 1 + p 2 1 + p 2 2 + p 2 3 + . . . . + p 2 k 2 ) ∗ . . . ∗ ( 1 + p n 1 + p n 2 + p n 3 + . . . . + p n k n ) s=(1+p^1_1+p^2_1+p^3_1 + .... + p^{k^1}_1) * (1+p^1_2+p^2_2+p^3_2 + .... + p^{k^2}_2) * ... * (1+p^1_n+p^2_n+p^3_n + .... + p^{k^n}_n) s=(1+p11+p12+p13+....+p1k1)∗(1+p21+p22+p23+....+p2k2)∗...∗(1+pn1+pn2+pn3+....+pnkn)
我们知道两个同底数次幂相乘,指数相加,即
a b ∗ a c = a b + c a^b * a^c = a^{b + c} ab∗ac=ab+c
所以当我们要求 a b a^b ab 的所有因数的和时,不妨先考虑底数 a a a 的分解,当我们得到 a a a 的分解后,对于任意的 p i k i p^{k_i}_i piki 只需要视为 p i b ∗ k i p^{b * k_i}_i pib∗ki 即可,但由于 b ≤ 5 ∗ 1 0 7 b \le 5 * 10^7 b≤5∗107 所以我们可以考虑欧拉降幂,即
a b = a b m o d ϕ ( p ) + ϕ ( p ) ( m o d p ) a^b = a^{b \mod \phi(p) + \phi(p)}(\mod p) ab=abmodϕ(p)+ϕ(p)(modp)
分析完毕。
代码
#include <iostream>
#include <vector>
using namespace std;
#define ll long long
const ll MOD = 9901;
// p 为质数,所以phi(p) = p - 1
const ll phi = 9900;
struct Prim {
ll p, cnt;
};
ll quick_mi(ll a, ll b) {
ll res = 1;
while (b) {
if (b % 2) res = res * a % MOD;
a = a * a % MOD;
b /= 2;
}
return res;
}
vector<Prim> ans;
void fenjie(ll n) {
for (ll x = 2; x * x <= n; x++) {
if (n % x) continue;
ll cnt = 0;
while (n % x == 0) cnt++, n /= x;
ans.push_back({ x, cnt });
}
if (n > 1) ans.push_back({ n, 1 });
}
int main() {
ll a, b, s = 1;
cin >> a >> b;
if (a == 1 || b == 0) {
cout << 1;
return 0;
}
fenjie(a);
for (auto& it : ans) {
ll temp = 1;
it.cnt = it.cnt * b;
it.cnt = it.cnt >= phi ? it.cnt % phi + phi : it.cnt;
ll temp_s = 0;
for (int x = 0; x <= it.cnt; x++) {
temp_s = (temp_s + temp) % MOD;
temp = temp * it.p % MOD;
}
s = s * temp_s % MOD;
}
printf("%lld\n", s % MOD);
return 0;
}