LOJ10211 Sumdiv

@Pelom  October 11, 2021

题意:

求 $A^B$ 的所有约数之和 $\bmod \ 9901$ 。

数据范围: $0\le A,B\le 5\times 10^7$

题解:

由算术基本定理:
$$A=\prod_{i=1}^k p_i^{a_i}$$
所以:
$$A^B=\prod_{i=1}^k p_i^{Ba_i}$$
其约数和为:
$$\prod_{i=1}^k \sum_{j=0}^{Ba_i} p_i^j$$
其中 $\sum\limits_{j=0}^{Ba_i} p_i^j$ 的部分为等比数列前 $n$ 项和,可用公式解决:
$$\sum\limits_{j=0}^{Ba_i} p_i^j=\frac{1-p_i^{Ba_i}}{1-p_i}$$
考虑到需要取模,分母 $1-p_i$ 部分应转化为其逆元,即:
$$\sum\limits_{j=0}^{Ba_i} p_i^j \equiv (1-p_i^{Ba_i}) \cdot (1-p_i)^{-1} \ (\bmod \ 9901)$$

代码:

#include<iostream>
#include<cstdio>
#include<memory.h>
using namespace std;
#define int long long
const int mod=9901;
const int N=5e7+10; 
int a,b;
int cnt,ans=1;
int pri[N],c[N];
bool isP[N];
inline int Pow(int x,int y,int p){
    int res=1;
    for(;y;y>>=1){
        if(y&1)
            (res*=x)%=p;
        (x*=x)%=p;
    }
    return res;
}
inline int inv(int x,int p){
    return Pow(x,p-2,p);
}
signed main(){
    scanf("%lld%lld",&a,&b);
    for(int i=2;i*i<=a;i++)
        if(a%i==0){
            pri[++cnt]=i;
            for(;a%i==0;a/=i)
                c[cnt]++;
            c[cnt]*=b;
        }
    if(a>1){
        pri[++cnt]=a;
        c[cnt]=b;
    }
    for(int i=1;i<=cnt;i++)
        (ans*=(Pow(pri[i],c[i]+1,mod)-1)*(inv(pri[i]-1,mod)))%=mod;
    printf("%lld",ans);
    return 0;
}

添加新评论