约数之和。

约数之和

题意:

求出 a b a^b ab的约数之和。

思路:

将a分解质因数得 a = p 1 n u m 1 ∗ p 2 n u m 2 ∗ . . . . . . p n n u m n a=p_1^{num1}*p_2^{num2}*......p_n^{numn} a=p1num1p2num2......pnnumn,那么 a b a^b ab分解质因数就是 a = p 1 n u m 1 + b ∗ p 2 n u m 2 + b ∗ . . . . . . p n n u m n + b a=p_1^{num1+b}*p_2^{num2+b}*......p_n^{numn+b} a=p1num1+bp2num2+b......pnnumn+b,于是:约数之和就为 s u m = ( 1 + p 1 + p 1 2 + . . . + p 1 n u m 1 + b ) ∗ ( 1 + p 2 + p 2 2 + . . . + p 2 n u m 2 + b ) ∗ . . . ∗ ( 1 + p n + p n 2 + . . . + p n n u m n + b ) sum=(1+p_1+p_1^2+...+p_1^{num1+b})*(1+p_2+p_2^2+...+p_2^{num2+b})*...*(1+p_n+p_n^2+...+p_n^{numn+b}) sum=(1+p1+p12+...+p1num1+b)(1+p2+p22+...+p2num2+b)...(1+pn+pn2+...+pnnumn+b)
上面这个式子由乘法分配定理得到,可以很轻易的想到,要得到所有的约数,只需要让不同的质因数的不同次方相乘即可。
然后发现这个式子括号里的每一项都是等比数列,所以只需要用等比数列求和公式: s = a 1 ∗ ( 1 − q n ) / ( 1 − q ) s=a_1*(1-q^n)/(1-q) s=a1(1qn)/(1q),用到这里要稍微转换一下: s = a 1 ∗ ( q n − 1 ) / ( q − 1 ) s=a_1*(q^n-1)/(q-1) s=a1(qn1)/(q1)然后用快速幂逆元取模即可,要注意,当分子取模为0时,逆元是不存在的,但既然分子取模为0,即 a 1 ∗ ( q n − 1 ) a_1*(q^n-1) a1(qn1)% m o d = 0 mod=0 mod=0,因为这里 a 1 a_1 a1为1,所以 ( q n − 1 ) (q^n-1) qn1% m o d = 0 mod=0 mod=0,所以 q n q^n qn% m o d = 1 mod=1 mod=1,此时这个等比数列的值 s = 项 数 s=项数 s=

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int mod = 9901;

int cnt;
int pri[1000010];
int vis[1000010];
int ans[1000010];
int num[1000010];
ll qpow(ll a,ll b)
{
	ll res = 1;
	while(b)
	{
		if(b%2)res = res*a%mod;
		b = b>>1;
		a = a*a%mod;
	}
	return res;
}
void oula()
{
	for(int i = 2; i <= 1000000; i++)
	{
		if(!vis[i])pri[++cnt] = i;
		for(int j = 1; j <= cnt && pri[j]*i <= 1000000; j++)
		{
			vis[i*pri[j]] = 1;
		}
	}
}
int main()
{
	__int128 p;
	oula();
	ll a,b;
	cin>>a>>b;
	if(a == 0)
	{
		cout<<0<<endl;
		return 0;
	}
	int c = 0,now = a;
	for(int i = 1; i <= cnt; i++)
	{
		now = a;
		if(pri[i] > now)break;
		if(now%pri[i] == 0)ans[++c] = pri[i];
		while(now%pri[i]==0)
		num[c]++,now/=pri[i];
	}
	ll res = 1;
	for(int i = 1; i <= c; i++)
	{
		if((qpow(ans[i],b*num[i]+1)+mod-1)%mod != 0)
		res *= (qpow(ans[i],b*num[i]+1)+mod-1)%mod*qpow(ans[i]-1,mod-2)%mod;
		else res*=(num[i]*b+1)%mod; 
		res%=mod;
	}
	cout<<(res)%mod<<endl;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值