传送门
题目翻译,不想写不想写
求 A B A^{B} AB的所有约数之和mod 9901 9901 9901的值
根据约数和定理, A B A^{B} AB的因子和为 ( 1 + p 1 + p 1 2 + . . . + p 1 c 1 ∗ B ) ∗ . . . ∗ ( 1 + p m + p m 2 + . . . + p m c m ∗ B (1+{p_{1}}+{p_{1}^{2}}+...+{p_{1}}^{c_{1}*B})*...*(1+{p_{m}}+{p_{m}^{2}}+...+{p_{m}}^{c_{m}*B} (1+p1+p12+...+p1c1∗B)∗...∗(1+pm+pm2+...+pmcm∗B
括号中的每一项都是一个等比数列,可以使用等比数列前N项和公式求值。而前N项和公式需要除法取模,因此需要求分母 1 − p i 1-p_{i} 1−pi在模 9901 9901 9901下的逆元,逆元根据费马小定理求解。
如果逆元存在,则求逆元,然后快速幂乘法运算
如果逆元不存在,即 1 − p 1-p 1−p是 9901 9901 9901的倍数,则 p % 9901 = 1 p \%9901=1 p%9901=1,即该等比数列的和对 9901 9901 9901取模后的值为项数N,即 c i + 1 c_{i}+1 ci+1
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
#define mem(a, b) memset(a, b, sizeof a)
typedef long long ll;
ll p[33], c[33], ind;
ll a, b;
ll qc(ll x,ll y,ll mod)
{
// 快速乘
return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod;
}
ll qpow(ll x, ll y, ll m){
// 快速幂
ll res = 1;
res %= m;
while (y){
if(y & 1){
res = qc(res, x, m);
}
y >>= 1;
x = qc(x, x, m);
}
return res % m;
}
void divide(ll n){
// 算数基本定理
ind = 0;
mem(p, 0);
mem(c, 0);
ll temp = n;
for (int i = 2; i * i <= temp; i++){
if (n % i == 0){
p[++ind] = i;
while (n % i == 0){
n /= i;
c[ind]++;
}
}
}
if (n > 1){
p[++ind] = n;
c[ind]++;
}
for (int i = 1; i <= ind; i++){
c[i] *= b;
}
}
ll euler(ll n){
// 欧拉函数
ll ans = n;
for (int i = 2; i * i <= n; i++){
if (n % i == 0){
ans = ans * (n - 1) / n;
while (n % i == 0){
n /= i;
}
}
}
if (n > 1){
ans = ans * (n - 1) / n;
}
return ans;
}
ll ans;
int main(){
// freopen("in.in", "r", stdin);
// freopen("out.out", "w", stdout);
scanf("%lld %lld", &a, &b);
divide(a);
ans = 1;
for (int i = 1; i <= ind; i++){
if ((1 - p[i]) % 9901 == 0){
// 逆元不存在
ans = ans * ((c[i] + 1) % 9901);
ans %= 9901;
}
else {
// 逆元存在
ll inv;
inv = qpow(1 - p[i], (euler(9901) - 1) % 9901, 9901);
ans = qc(ans, qc((1 - qpow(p[i], c[i] + 1, 9901)), inv, 9901), 9901);
ans %= 9901;
}
}
printf("%lld\n", ans);
return 0;
}
约数和定理简单证明如下