[清华集训2012]模积和

Description

Luogu2260
BZOJ2956


\[ \sum_{i=1}^{n}\sum_{j=1}^{m} (n\bmod i)(m\bmod j)[i \ne j] \]

Solution

看到取模就会想整除分块的吧,那个\([i\ne j]\)其实也很好处理啊,就是最后再减去\(i=j\)的情况就行了。
我式子推的有点丑……

\[ \sum_{i=1}^{n}\sum_{j=1}^{m} (n\bmod i)(m\bmod j)[i \ne j]\\ = \sum_{i=1}^{n}\sum_{j=1}^{m} (n\bmod i)(m\bmod j) - \sum_{i=1}^{\min(n, m)} (n\bmod i)(m\bmod i)\\ = \sum_{i=1}^{n}\sum_{j=1}^{m} (n - \lfloor\dfrac{n}{i}\rfloor i)(m - \lfloor\dfrac{m}{j}\rfloor j) - \sum_{i=1}^{\min(n, m)} (n - \lfloor\dfrac{n}{i}\rfloor i)(m - \lfloor\dfrac{m}{i}\rfloor i)\\ = \sum_{i=1}^{n}\sum_{j=1}^{m} (nm - m\lfloor\dfrac{n}{i}\rfloor i - n\lfloor\dfrac{m}{j}\rfloor j + \lfloor\dfrac{n}{i}\rfloor i\lfloor\dfrac{m}{j}\rfloor j) - \sum_{i=1}^{\min(n, m)}\mbox{...}\\ = n^2m^2 - m^2\sum_{i=1}^{n}\lfloor\dfrac{n}{i}\rfloor i - \mbox{...} \]
后面就是一些sb的去括号了,没啥好说的了。

Code

#include <cstdio>
#include <algorithm>

typedef long long LL;
const LL MOD = 19940417;
const LL I2 = 9970209;
const LL I6 = 3323403;

int n, m;

LL sp(LL x) {
    return x * (2 * x + 1) % MOD * (x + 1) % MOD * I6 % MOD;
}

int main() {
    scanf("%d%d", &n, &m);
    if (n < m) std::swap(n, m);
    LL ans = n % MOD * n % MOD * m % MOD * m % MOD;
    LL si = 0, sj = 0, sij = 0;
    for (int i = 1, j; i <= n; i = j+1) {
        j = n / (n / i);
        si = (si + (n / i) * (i + j) % MOD * (j - i + 1) % MOD * I2 % MOD) % MOD; 
    }
    for (int i = 1, j; i <= m; i = j+1) {
        j = m / (m / i);
        sj = (sj + (m / i) * (i + j) % MOD * (j - i + 1) % MOD * I2 % MOD) % MOD; 
    }
    ans = ((ans - m % MOD * m % MOD * si % MOD - n % MOD * n % MOD * sj % MOD) %MOD + MOD) % MOD;
    sij = si * sj % MOD;
    ans = (ans + sij) % MOD;
    ans = (ans - m % MOD * m % MOD * n % MOD + MOD) % MOD;
    si = 0;
    for (int i = 1, j; i <= m; i = j+1) {
        j = std::min(m, n / (n / i));
        si = (si + (n / i) * (i + j) % MOD * (j - i + 1) % MOD * I2 % MOD) % MOD; 
    }
    ans = (ans + m % MOD * si % MOD + n % MOD * sj % MOD) % MOD;
    sj = 0;
    for (int i = 1, j; i <= m; i = j+1) {
        j = std::min(n / (n / i) , m / (m / i));
        sj = (sj + (n / i) % MOD * (m / i) % MOD * (sp(j) - sp(i-1) + MOD) % MOD) % MOD; 
    }
    ans = (ans - sj + MOD) % MOD;
    printf("%d\n", ans);
    return 0;
}

转载于:https://www.cnblogs.com/wyxwyx/p/lg2260.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值