POJ 1845 Sumdiv

本文介绍了一种求解模意义下数的所有正约数之和的方法,利用数的质因数分解,并结合等差数列求和公式,通过编程实现高效计算。

模意义下的运算

对于一个数 \(N\) 来说,可以分解成 \[N=p_1 ^ {c_1}p_2^{c_2}\cdots P_m ^ {c_m}\]

\(N\) 的所有正约数的和可表示为:
\[(1 + p_1 + p_1 ^2 + \cdots p_1 ^ {c_1})* \cdots *(1 + p_m + p_m ^2 + \cdots + p_m ^{c_m}) = \prod_{i =1}^1(\sum_{j = 1}^{c_1}(p_j)^i)\]

对于 \(N^B\) 来说,所有正约数的和可表示为:
$\[$(1 + p_1 + p_1 ^2 + \cdots p_1 ^ {c_1 * B})* \cdots *(1 + p_m + p_m ^2 + \cdots + p_m ^{c_m * B}) = \prod_{i =1}^1(\sum_{j = 1}^{c_j * B}(p_j)^i)\]
那么对于每个质因数来说都是一个等差数列求和,运用等差数列求和公式做即可,对于除法来说,转换为乘上他的逆元, 因为 9901 是一个质数,所以对于 \(P_i - 1\)这个数来说,如果他不是 9901 的倍数,那么他就有逆元, 如果他是倍数,等差数列的公比就变为了 1

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define ll long long
using namespace std;
const int MOD = 9901;
ll Qfactor[100][2], tot, A, B, ans = 1ll;
void divide(ll n) {
    for(ll i = 2; i * i <= n; i++) {
        if(!(n % i)) {
            Qfactor[++tot][0] = i;
            while(!(n % i)) {Qfactor[tot][1]++; n /= i;}
        }
    }
    if(n > 1) {Qfactor[++tot][0] = n; Qfactor[tot][1] = 1;}
}
ll quick_mod(ll n, ll k) {
    ll ans = 1;
    while(k) {
        if(k & 1ll) (ans *= n) %= MOD;
        (n *= n) %= MOD;
        k >>= 1;
    }
    return ans;
}
int main() {
    cin>>A>>B;
    divide(A);
    for(int i = 1; i <= tot; i++) {
        if(!((Qfactor[i][0] - 1) % MOD)) (ans *= Qfactor[i][1] * B + 1) %= MOD;
        else {
            (ans *= (quick_mod(Qfactor[i][0], Qfactor[i][1] * B + 1) - 1 + MOD) % MOD) %= MOD;
            (ans *= quick_mod(Qfactor[i][0] - 1, MOD - 2)) %= MOD;
        }
    }
    cout<<ans<<endl;
    return 0;
}

转载于:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8545487.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值