约数之和(acwing)

题目链接

题目

img

思路

最开始的思路:

把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;
}

posted @ 2020-10-28 17:40  GoodVv  阅读(113)  评论(0编辑  收藏  举报