1 条题解
-
0
为计算 所有自然数除数之和对 取模的结果,可按照以下步骤进行:
1. 质因数分解
任何大于 的自然数 都能写成若干个质数幂次乘积的形式,即 $A = p_1^{a_1} \times p_2^{a_2} \times \cdots \times p_n^{a_n}$,其中 是质数, 是正整数。那么 可表示为 $A^B = p_1^{a_1B} \times p_2^{a_2B} \times \cdots \times p_n^{a_nB}$。
2. 计算 所有除数之和
若一个数 分解质因数后为 $N = p_1^{k_1} \times p_2^{k_2} \times \cdots \times p_m^{k_m}$,那么 的所有除数都可写成 $p_1^{x_1} \times p_2^{x_2} \times \cdots \times p_m^{x_m}$ 的形式,其中 。
所以 的所有除数之和 为: $S_N = \prod_{i = 1}^{m} (1 + p_i + p_i^2 + \cdots + p_i^{k_i})$
对于 $A^B = p_1^{a_1B} \times p_2^{a_2B} \times \cdots \times p_n^{a_nB}$,其所有除数之和 为: $S = \prod_{i = 1}^{n} (1 + p_i + p_i^2 + \cdots + p_i^{a_iB})$
3. 计算等比数列和
式子中的每一项 是首项为 ,公比为 ,项数为 的等比数列之和。根据等比数列求和公式 (这里 ,,)可得: $1 + p_i + p_i^2 + \cdots + p_i^{a_iB}=\frac{p_i^{a_iB + 1}-1}{p_i - 1}$
4. 取模运算
由于最终结果要对 取模,所以在计算过程中需要进行取模操作,以避免数值溢出。在计算等比数列和时,涉及到除法运算,在模运算下,需要计算分母的逆元。根据费马小定理,若 是质数, 是整数且 与 互质,那么 ,则 在模 意义下的逆元为 。这里 是质数,所以 在模 9901 意义下的逆元为 。
5. 特殊情况处理
- 当 时,若 ,根据数学定义, 规定为 1,此时所有除数之和为 1;若 ,,所有除数之和为 0。
- 当 时,,所有除数之和为。
6. 快速幂算法
在计算 和 时,可使用快速幂算法,将时间复杂度从 降低到 。快速幂的核心思想是将指数表示为二进制形式,通过不断平方和乘法操作来快速计算幂次。
综上所述,整个算法先对 进行质因数分解,接着计算每个质因数对应的等比数列和,在计算过程中运用快速幂算法和取模运算,最后将所有结果相乘得到 所有除数之和对 取模的结果。
#include <iostream> #include <cmath> #include <string> #include <cstring> #include <algorithm> #include <cstdio> using namespace std; typedef long long ll; #define INF 0xfffffff #define MAX(a,b) a>b?a:b #define MIN(a,b) a>b?b:a ll pow_mod(ll x,ll y,ll MOD) //快速幂mod(递归实现) 求逆元。 { if(y==1) return x; ll ans=pow_mod(x,y/2,MOD); return y%2?((ans*ans)%MOD*x)%MOD:(ans*ans)%MOD; } int main() { ll i,j,k,t; ll m,n; ll ans; ll MOD=9901; ll temp; while(scanf("%I64d %I64d",&n,&k)!=-1) { if(k==0||n==0) cout<<"1"<<endl; //此处坑啊。 else { ans=1; int Count=0; if(n%2==0) { while(n%2==0) { n/=2; Count++; } ll y=(Count*k+1)%(MOD-1); ans=(ans*((pow_mod(2,y,MOD)+MOD-1)%MOD))%MOD; } for(i=3;i*i<n&&n!=1;i+=2) { if(n%i==0) { Count=0; while(n%i==0) { n/=i; Count++; } if((i-1)%MOD==0) //如果p-1是MOD倍数的特殊情况,此时没有逆元 { ans=ans*(Count*k+1)%MOD; } else { temp=pow_mod(i-1,MOD-2,MOD); //temp就是求的逆元 ll y=(Count*k+1)%(MOD-1); //由于MOD的数是素数,利用了费马小定理 ans=(ans*(((temp*pow_mod(i,y,MOD))%MOD-temp+MOD)%MOD))%MOD; } } } if(n!=1) { if((n-1)%MOD!=0) { temp=pow_mod(n-1,MOD-2,MOD); ans=(ans*((temp*pow_mod(n,k+1,MOD)%MOD-temp+MOD)%MOD))%MOD; } else { ans=ans*(k+1)%MOD; } } printf("%I64d\n",ans); } } return 0; }
- 1
信息
- ID
- 846
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 3
- 已通过
- 1
- 上传者