【SSOJ 2913: 「一本通 6.4 例 3」Sumdiv】题解

题目

原题来自:Romania OI 2002

\(A^B\) 的所有约数之和 \(\bmod 9901\)

思路

首先按照算术基本定理:

\[\Large A=p_1^{k_1}\times p_2^{k_2}\times\cdots\times p_n^{k_n} \]

所以:

\[\Large A^B=p_1^{k_1\times B}\times p_2^{k_2\times B}\times\cdots\times p_n^{k_n\times B} \]

然后根据约数和公式:

\[\Large ans=(p_1^0+p_1^1+\cdots+p_1^{k_1\times B})\times (p_2^0+p_2^1+\cdots+p_2^{k_2\times B})\times\cdots\times(p_n^0+p_n^1+\cdots+p_n^{k_n\times B}) \]

然后根据等比数列求和公式:

\[\Large ans=\frac{p_1^{k_1\times B+1}-1}{p_1-1}\times \frac{p_2^{k_2\times B+1}-1}{p_2-1}\times\cdots \times\frac{p_n^{k_n\times B+1}-1}{p_n-1} \]

然后就解出来了。

总结

这是一道非常综合的题,考察知识点主要有四个:

  1. 算术基本定理(质因数分解)
  2. 约数和公式
  3. 等比数列求和公式
  4. 求逆元(费马小定理+快速幂)

每一个知识点都尤为重要,只要懂得这些知识点,这道题就迎刃而解了。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read(){int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;
ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+
(x<<3)+(ch^48);ch=getchar();}return x*f;}
//#define N
//#define M
#define mo 9901
int n, m=1, i, j, k; 
int a, b; 

int kuai(int a, int b)
{
	int ans=1; 
	while(b)
	{
		if(b&1) ans=(ans*a)%mo; 
		a=(a*a)%mo; 
		b>>=1; 
	}
	return ans; 
}

int deng(int x, int n)
{
	return (kuai(x, n+1)-1)*kuai(x-1, mo-2)%mo; 
}

signed main()
{
//	freopen("tiaoshi.in","r",stdin);
//	freopen("tiaoshi.out","w",stdout);
	a=read(); b=read(); 
	for(i=2; i<=a; ++i)
		if(a%i==0)
		{
			k=0; while(a%i==0) ++k, a/=i; 
			// printf("deng(%lld, %lld)=%lld\n", i, k*b, deng(i, k*b)); 
			m*=deng(i, k*b); 
			m%=mo; 
		}
	printf("%lld", (m%mo+mo)%mo); 
	return 0;
}

posted @ 2022-01-18 11:43  zhangtingxi  阅读(143)  评论(0编辑  收藏  举报