1. 程式人生 > 實用技巧 >約數之和(acwing)

約數之和(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;
}