因子和(luoguP1593)(等比数列求和+逆元)

输入两个正整数\(a\)\(b\),求\(a\cdot b\)的因子和。结果太大,只要输出它对9901的余数。

Input

仅一行,为两个正整数\(a\)\(b\)(\(0≤a,b≤50000000\))。

Output

a^b的因子和对9901的余数。

Sample Input

2 3

Sample Output

15

题意:

中文题面,不解释。

题解:

\(a^b\)分为\(b\)\(a\)相乘,然后再处理。

\(a=p_1^{c_1}p_2^{c_2}…p_n^{c_n}\)

\(a\)的所有因数和为

\(\sum_{i_1=0}^{c_1}\sum_{i_2=0}^{c_2}…\sum_{i_n=0}^{c_n}p_1^{i_1}p_2^{i_2}…p_n^{i_n}\)

然后我们可以发现每个因数是独立的,可以提出来变成

\(\prod_{i=1}^{n}\sum_{j=0}^{c_i}p_i^j\)

现在可以对每一个因数分开处理了
拆开\(\sum\)发现变成了一个等比数列:

\(1+p^1+p^2+p^3+…+p^c\)

然后套一下等比数列的公式成了

\(\frac{p^{c-1}-1}{p-1}\)

最后答案就是

\(\prod_{i=1}^n\frac{p_i^{c_i-1}-1}{p_i-1}\)

额,还要乘上\(b\)

\(\prod_{i=1}^n\frac{p_i^{c_ib-1}-1}{p_i-1}\)

这里的分母就要用逆元来乘,但因为有时\(p_i-1\)会是9901的倍数,这时直接把答案乘上这个因数的个数就行了。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
const ll p=9901;
ll mpow(ll a,ll n){
	ll ret=1;
	while(n){
		if(n&1)ret=ret*a%p;
		a=a*a%p;
		n/=2;
	}
	return ret;
}
ll a,b,ans=1;
ll prime[1000000],js[1000000],m;
main(){
	cin>>a>>b;
	int n=a;
	for(ll i=2;i*i<=n;++i){
		if(n%i==0)prime[++m]=i;
		while(n%i==0){
			js[m]++;
			n/=i;
		}
	}
	if(n!=1){
		prime[++m]=n;
		js[m]=1;
	}
	for(ll i=1;i<=m;++i){
		if(prime[i]%p==1){
			ans=(ans*(js[i]+1))%p;
			continue;
		}
		ll S=(mpow(prime[i],js[i]*b+1)-1)*mpow(prime[i]-1,p-2)%p;
		ans=(ans*S)%p;
	}
	cout<<ans%p<<endl;
}
posted @ 2018-12-11 13:42  整理者  阅读(283)  评论(0编辑  收藏  举报