【POJ 1845】Sumdiv(逆元解法)

本文介绍了一个特定的数学问题:求解AB的模9901所有约数之和,并给出了一种有效的算法实现。通过将AB分解质因数并利用等比数列求和公式进行计算,结合费马小定理处理模意义下的除法运算。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述

ABAB 的所有约数之和 mod9901mod99011A,B5×1071≤A,B≤5×107

算法分析

根据之前博客的题解,ABAB 的约数之和为 (p00+p10+...+pc0B0)×(p01+p11+...+pc1B1)×...×(p0n+p1n+...+pcnBn)(p00+p01+...+p0c0B)×(p10+p11+...+p1c1B)×...×(pn0+pn1+...+pncnB)

利用等比数列求和公式计算即可,公式涉及除法时可以使用费马小定理计算出分母的逆元。

注意,在模意义下,减去一个数后一定要再加上模数,不然结果可能出现负数。

代码实现

#include <cstdio>
#include <vector>
typedef long long int ll;
const ll mod=9901;
std::vector<ll> prime;
std::vector<ll> times;
inline void divide(ll n) {
    for(ll i=2;i*i<=n;++i) {
        if(n%i==0) {
            prime.push_back(i);ll cnt=0;
            while(n%i==0) {n/=i;++cnt;}
            times.push_back(cnt);
        }
    }
    if(n>1) {prime.push_back(n);times.push_back(1);}
}
inline ll qpow(ll n,ll k) {
    ll ans=1;
    while(k) {
        if(k&1) ans=ans*n%mod;
        n=n*n%mod;k>>=1;
    }
    return ans;
}
int main() {
    ll a,b;scanf("%lld%lld",&a,&b);
    divide(a);
    ll ans=1;
    for(int i=0,end=prime.size();i<end;++i) {
        times[i]*=b;
        if((prime[i]-1)%mod==0) ans=ans*(times[i]+1)%mod;
        else ans=ans*((qpow(prime[i],times[i]+1)-1+mod)*qpow(prime[i]-1,mod-2)%mod)%mod;
    }
    printf("%lld\n",ans);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值