504 字
3 分钟
BZOJ 2956 模积和
2019-08-06

题目#

BZOJ-2056

一道有点复杂的数论分块。

公式推导#

所求即为:

∑i=1n∑j=1m(n mod i)⋅(m mod j)(i≠j)\sum_{i=1}^{n}\sum_{j=1}^{m}{(n \bmod i )\cdot (m\bmod j)(i \neq j)}

先不管i≠ji\neq j的情况: ∑i=1n(∑j=1m(n mod i)⋅(m mod j))\sum_{i=1}^{n}(\sum_{j=1}^{m}{(n\bmod i) \cdot (m\bmod j)})

∑i=1n∑j=1m(n−i⌊ni⌋)(m−j⌊mj⌋)\sum_{i=1}^{n}\sum_{j=1}^{m}{(n-i\lfloor \frac{n}{i} \rfloor)(m-j\lfloor \frac{m}{j} \rfloor)}

∑i=1n∑j=1m(nm−n⋅j⌊mj⌋−m⋅i⌊ni⌋+ij⌊ni⌋⌊mj⌋)\sum_{i=1}^{n}\sum_{j=1}^{m}{(n m - n\cdot j\lfloor \frac{m}{j} \rfloor - m\cdot i\lfloor \frac{n}{i} \rfloor + ij\lfloor \frac{n}{i} \rfloor \lfloor \frac{m}{j} \rfloor)}

n2m2−n2∑j=1mj⌊mj⌋−m2∑i=1ni⌊ni⌋+∑i=1ni⌊ni⌋∑i=1mj⌊mj⌋n^2m^2 - n^2\sum_{j=1}^{m}{j\lfloor \frac{m}{j} \rfloor} - m^2\sum_{i=1}^{n}i\lfloor \frac{n}{i} \rfloor + \sum_{i=1}^{n}i\lfloor \frac{n}{i} \rfloor\sum_{i=1}^{m}j\lfloor \frac{m}{j} \rfloor

然后在讨论i=ji = j的情况:

∑i=1min(n,m)(n mod i)⋅(m mod i)\sum_{i=1}^{min(n, m)}{(n\bmod i)\cdot (m\bmod i)}

∑i=1min(n,m)(n−i⌊ni⌋)(m−i⌊mi⌋)\sum_{i=1}^{min(n, m)}{(n - i\lfloor \frac{n}{i} \rfloor)(m - i\lfloor \frac{m}{i} \rfloor)}

∑i=1min(n,m)nm−m⋅i⌊ni⌋−n⋅i⌊mi⌋+i2⌊ni⌋⌊mi⌋\sum_{i=1}^{min(n, m)}{n m - m\cdot i\lfloor \frac{n}{i} \rfloor - n\cdot i\lfloor \frac{m}{i} \rfloor + i^2 \lfloor \frac{n}{i} \rfloor \lfloor \frac{m}{i} \rfloor}

然后就可以愉快的分块了。

代码#

/**************************************************************
Problem: 2956
User: Dicer
Language: C++
Result: Accepted
Time:184 ms
Memory:1292 kb
****************************************************************/
#include<bits/stdc++.h>
#define rep(i, a, b) for(int i = (a); i <= (int)(b); ++i)
#define per(i, a, b) for(int i = (a); i >= (int)(b); --i)
#define debug(x) cout << #x << ' ' << x << endl;
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 7;
const int MOD = 19940417;
const int INV = 3323403;
ll cal(ll n){
ll ans = 0;
for(ll i = 1, j; i <= n; i = j + 1){
j = n / ( n / i);
ans += (i + j) * (j - i + 1) / 2 * (n / i);
ans %= MOD;
}
return ans;
}
ll cal(ll n, ll k){
ll ans = 0;
for(ll i = 1, j; i <= k; i = j + 1){
j = min(k, n / ( n / i));
ans += (i + j) * (j - i + 1) / 2 * (n / i);
ans %= MOD;
}
return ans;
}
ll sum(ll n){
return n * (n + 1) % MOD * (2 * n + 1) % MOD * INV % MOD;
}
ll cal(ll n, ll m, ll k){
ll ans = 0;
for(ll i = 1, j; i <= k; i = j + 1){
j = min(k, min(n / (n / i), m / (m / i)));
ans += (sum(j) - sum(i-1)) * (n/i) % MOD * (m/i) % MOD;
ans %= MOD;
}
return ans;
}
ll mul(ll a, ll b){
a %= MOD; b %= MOD;
return a * b % MOD;
}
int main(){
ll n, m, k;
scanf("%lld%lld", &n, &m);
k = min(n, m);
long long ans = 0;
ans += mul(n * n, m * m);
ans -= mul(n * n, cal(m));
ans -= mul(m * m, cal(n));
ans += mul(cal(n), cal(m));
ans = ((ans % MOD) + MOD) % MOD;
ans -= mul(k, n * m);
ans += mul(n, cal(m, k));
ans += mul(m, cal(n, k));
ans -= cal(n, m, k);
ans = ((ans % MOD) + MOD) % MOD;
printf("%lld\n", ans);
return 0;
}
BZOJ 2956 模积和
https://dicer-zz.github.io/posts/bzoj-2956/
作者
Dicer
发布于
2019-08-06
许可协议
CC BY-NC 4.0
Get in Touch
WeChat
Dicer__