一本通OJ-约数之和

约数之和

题意

\(A^B\)\(\mod {P}\)意义下的约数之和。

分析

先来看一个简单的问题,对于一个数\(n\),若\(n=p_{1}^{m_{1}}*p_{2}^{m_{2}}...*p_{n}^{m_{n}}\)。对于\(p_{i}\)在和中贡献\(\sum\limits_{j=0}^{m_{i}}p_i^{j}\)。则约数和为\(\prod\limits_{i=1}^n (\sum\limits_{j=0}^{m_{i}}p_i^{j})\)。易对于\(A^B\)来说\(Ans=\prod\limits_{i=1}^n (\sum\limits_{j=0}^{B*m_{i}}p_i^{j})\)。我们考虑设

\(①:x=p_{1}^{0}+p{2}^{1}...p^m\)

\(②:px=p_{}^{1}+p{}^{2}...p^{m+1}\)

\(②-①\) 则得\(x=\frac{p_{i}^{Bk_{i}+1}-1}{p_{i}-1}\)

\(Ans=\prod\limits_{i=1}^n(\frac{p_{i}^{Bk_{i}+1}-1}{p_{i}-1})\)

\(9901\mid p_{i}-1\)时,相当于直接\(/9901\)。否则求\(p_{i}-1\)的逆元。

代码

#include<bits/stdc++.h>
#define int long long
using namespace std;
int tot;
const int N=1e5+67;
int p[N],k[N];
const int mod=9901;
int a,b;
void get(int n){
	int i=2;
	while(n!=1){
		if(n%i==0){
			p[++tot]=i;
			while(n%i==0) n/=i,k[tot]++;
		}
		i++;
	}
}
int qpow(int shu,int cifang,int mod){
	int ans=1;
	int k=cifang;
	while(k){
		if(k&1){
			ans=ans*shu%mod;
			shu=shu*shu%mod;
		}
		else{
			shu=shu*shu%mod;
		}
		k>>=1;
	}
	return ans%mod;
}
int ans=1;
signed main(){
	scanf("%lld%lld",&a,&b);
	get(a);
	for(int i=1;i<=tot;i++){
		if((p[i]-1)%mod==0) ans=ans*(b*k[i]+1)%mod;
		else{
			int j=(qpow(p[i],k[i]*b+(long long)1,mod)-1+mod)%mod;
			int inv=qpow(p[i]-1,mod-(long long)2,mod);
			ans=ans*j*inv%mod;

		}
	}
	printf("%lld",ans);
	return 0;
}
posted @ 2023-07-25 13:57  Zimo_666  阅读(12)  评论(0编辑  收藏  举报