10211. 「一本通 6.4 例 3」Sumdiv[数论之约数与快速幂]

【题目描述】
原题来自:Romania OI 2002

求 ABAB 的所有约数之和 mod9901mod9901。

【输入】
输入两个整数 A,BA,B。

【输出】
输出答案 mod9901mod9901。

【输入样例】
2 3
【输出样例】
15
【提示】
样例说明

23=823=8,88 的所有约数为 1,2,4,81,2,4,8,1+2+4+8=151+2+4+8=15,15mod9901=1515mod9901=15,因此输出 1515。

数据范围与提示:

对于全部数据,0≤A,B≤5×1070≤A,B≤5×107。

分析:题目谈到约数和,我们就想到约数和的公式:
设A惟一分解后等于 p 1 a 1 p_1^{a1} p1a1× p 2 a 2 p_2^{a2} p2a2 p n a n p_n^{an} pnan,则A的约数和为
Π i = 1 n ( Σ j = 0 a i ( p i ) j ) \Pi_{i=1}^n(\Sigma_{j=0}^{ai}(p_i) ^j) Πi=1n(Σj=0ai(pi)j)
注意后者是一个等比数列,则想到等比数列求和公式,将其化简得到
Π i = 1 n ( p i a i + 1 − 1 p i − 1 ) \Pi_{i=1}^n(\frac{p_i^{ai+1}-1}{p_i-1}) Πi=1n(pi1piai+11)
带入题目要求的B和模数9901(质数)得到
a n s = Π i = 1 n ( p i a i × B + 1 − 1 p i − 1 m o d 9901 ) ans=\Pi_{i=1}^n(\frac{p_i^{ai ×B+1}-1}{p_i-1} mod 9901) ans=Πi=1n(pi1piai×B+11mod9901)
于是算出 p i − 1 p_i-1 pi1的乘法逆元即可
代码如下

#include<bits/stdc++.h>
#define ll long long
using namespace std;
ll a,B;
ll p[100010];
ll b[100010];
ll cnt;
ll KSM(ll j,ll k,ll l)
{
	ll ans=1;
	while(k)
	{
		if(k&1) ans=ans*j%l;
		j=j*j%l;
		k>>=1;
	}
	return ans;
}
int main()
{
	scanf("%lld%lld",&a,&B);//输入 
	for(ll i=2;i*i<=a;i++)
	{
		if(a%i==0)
		{
			p[++cnt]=i;
			while(a%i==0)
			{
				b[cnt]++;
				a/=i;
			}
		}
	}
	if(a>1)
	{
		p[++cnt]=a;
		b[cnt]=1;
	}//质因数分解,p为底数,b为指数 
	ll ans=1;
	for(ll i=1;i<=cnt;i++)
	{
		ans*=((KSM(p[i],b[i]*B+1,9901)+9900)%9901)*(KSM(p[i]-1,9901-2,9901))%9901;//算出答案
		//根据费马小定理,可知pi-1的乘法逆元是(pi-1)^(9901-2),用快速幂算出 
	}
	printf("%lld",ans%9901);//别忘了还要取模 
	return 0;
}

如有错误,可留言,谢谢

posted @ 2019-07-14 17:02  最爱丁珰  阅读(30)  评论(0编辑  收藏  举报