[清华集训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;
}

猜你喜欢

转载自www.cnblogs.com/wyxwyx/p/lg2260.html