一本通1633:【例 3】Sumdiv

#include <cstdio>
#define LL long long

const int mod = 9901;

LL qmi(LL a, LL b) {
    LL res = 1, mul = a;

    while (b) {
        if (b & 1)
            res = res * mul % mod;

        mul = mul * mul % mod;
        b >>= 1;
    }

    return res;
}

int main() {
    LL a, b, ans = 1;
    scanf("%lld %lld", &a, &b);

    for (int i = 2, j; i <= a / i; i ++)
        if (a % i == 0) {
            j = 0;

            while (a % i == 0)
                a /= i, j ++;

            j *= b;
            ans *= (1 - qmi(i, j + 1)) * qmi(1 - i, mod - 2) % mod;
            ans %= mod;
        }

    if (a > 1)
        ans *= (1 - qmi(a, b + 1)) * qmi(1 - a, mod - 2) % mod;

    ans %= mod;
    printf("%lld", ans);
    return 0;
}

这道题目是求一个表达式的结果,表达式中包含了欧拉函数和向下取整操作。需要注意的是,最后结果需要对一个给定的mod取模。 首先,我们可以把这个表达式分成两部分来计算。第一部分是计算φ(i)的前缀和,第二部分是计算⌊n/i⌋的前缀和。 对于第一部分,我们可以使用线性筛法来计算φ(i)的前缀和。具体步骤如下: 1. 初始化一个数组phi,大小为k+1,用来保存欧拉函数的值。 2. 初始化一个数组prime,用来保存质数。 3. 初始化一个数组isPrime,大小为k+1,用来标记是否是质数。 4. 初始化一个数组sumPhi,大小为k+1,用来保存φ(i)的前缀和。 5. 遍历2到k的每个数i,如果isPrime[i]为true,则将i加入到prime数组中,并且令phi[i] = i-1。 否则,找到i的最小质因数p,令phi[i] = phi[i/p] * p / (p-1)。 6. 遍历prime数组中的每个质数p,更新phi数组中所有p的倍数的值,令phi[i] = phi[i] * p / (p-1)。 7. 计算sumPhi数组的前缀和,即sumPhi[i] = sumPhi[i-1] + phi[i]。 对于第二部分,我们可以使用容斥原理来计算⌊n/i⌋的前缀和。具体步骤如下: 1. 初始化一个数组sumDiv,大小为k+1,用来保存⌊n/i⌋的前缀和。 2. 遍历1到k的每个数i,计算sumDiv[i] = sumDiv[i-1] + ⌊n/i⌋。 3. 使用容斥原理,减去所有的sumDiv[i] * φ(i),其中i为k的因子。 最后,将第一部分和第二部分的结果相乘,并对mod取模,即可得到最终结果。 以上就是求解这道题目的思路和步骤。希望对你有帮助!如果有任何疑问,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值