约数之和(acwing)
题目链接
题目
思路
最开始的思路:
把A拆成 \(a_1 \times a_2\) , 那么\(A^B\) 就变成了\(a_1^B \times a_2^B\) ,那么\(a1\)和\(a2\)能提供的因子(约数)有:
\(a_1^0\) , \(a_1^1\) , \(a_1^2\) \(\cdots a_1^B\)
\(a_2^0\) , \(a_2^1\) , \(a_2^2\)\(\cdots a_2^B\)
还有:
\(a_1^0 \times a_2^0\) ,\(a1^0 \times a2^1\),\(a_1^0 \times a_2^2\)\(\cdots\)
\(a_1^1 \times a_2^0\),\(a_1^1 \times a_2^1\),\(a_1^1 \times a_2^2\)\(\cdots\)
\(\cdots\)\(\cdots\)\(\cdots\)
用一个map记录是否出现过这个因子,然后计算约数和
但\(A , B\)范围在\(5^7\)所以必然T了
后来的思路:
一个数的因子,要么是质数,要么是数个质数的乘积
那么我把一个数拆成一堆的质因子相乘,这个数的所有约数都是由这些质因子转化来的
对任意数\(x\) , 根据唯一分解定理有:
\(x = p_1 ^{x_1} \times p_2 ^{x_2} \times p_3 ^{x_3}\ldots\times p_m ^{x_m}\)
也就是说\(x\)的某个因子\(v = p_1 ^{i_1} \times p_2 ^{i_2} \times p_3 ^{i_3}\ldots\times p_m ^{i_m}\)
然后问让你求所有因子的和也就是求:
$sum = (p_1 ^0 + p_1 ^{1} + p_1 ^{2}\ldots+ p_1 ^{x_1}) \times (p_2 ^0 + p_2 ^{1} + p_2 ^{2}\ldots+ p_1 ^{x_2})\times\ldots\times(p_m ^0 + p_m ^{1} + p_m ^{2}\ldots+ p_m ^{x_m}) $
为什么是这个公式,举个栗子:
\(A = 30 , B = 2\)
\(A = 2^1 \times 3^1 \times 5^1\)
\(A^B = (2^1 \times 3^1 \times 5^1)^B = 2^B \times 3^B \times 5^B = 2^2 \times 3^2 \times 5^2\)
对于质因子\(2\)来说:
\(2^0\)对答案的贡献是:\(2^0 \times (3^0 \times 5^0 + 3^0 \times 5^1 + 3^0 \times 5^2 + 3^1 \times 5^0 +\ldots +3^2 \times 5^2) = 2^0 \times(3^0 + 3^1 + 3^2) \times (5^0 + 5^1 + 5^2)\)
同理:\(2^1\)对答案的贡献是$ 2^1 \times(3^0 + 3^1 + 3^2) \times (5^0 + 5^1 + 5^2)$
等等等等\(...\)
#include<bits/stdc++.h>
#define int long long
#define ll long long
#define pb(a) push_back(a)
#define fi first
#define se second
#define mp(a , b) make_pair(a , b)
using namespace std;
ll pow_mod(ll x,ll n,ll mod){ll res=1;while(n){if(n&1)res=res*x%mod;x=x*x%mod;n>>=1;}return res;}//xμ?n′?·?mod
const int mod = 9901;
vector< pair<int , int> > vec;
signed main()
{
int a , b;
cin >> a >> b;
if(a == 0)return cout << "0\n" , 0;
else if(b == 0) return cout << "1\n" , 0;
for(int i = 2 ; i * i <= a ; i ++){
if(a % i == 0){
int cnt = 0;
while(a % i == 0) a /= i , cnt ++;
vec.pb(mp(i , cnt));
}
}
if(a != 1) vec.pb(mp(a , 1));
int ans = 1;
for(int i = 0 ; i < vec.size() ; i ++){
int now = (pow_mod(vec[i].fi , (b * vec[i].se) + 1 % mod , mod) - 1) * pow_mod(vec[i].fi - 1 , mod - 2 , mod);
if(vec[i].fi % mod == 1) now = vec[i].se * (b * vec[i].fi) % mod + 1 % mod;
ans *= now % mod , ans %= mod;
}
cout << (ans % mod + mod) % mod << '\n';
return 0;
}