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

题目#

BZOJ-2056

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

公式推导#

所求即为:

i=1nj=1m(nmodi)(mmodj)(ij)\sum_{i=1}^{n}\sum_{j=1}^{m}{(n \bmod i )\cdot (m\bmod j)(i \neq j)}

先不管iji\neq j的情况: i=1n(j=1m(nmodi)(mmodj))\sum_{i=1}^{n}(\sum_{j=1}^{m}{(n\bmod i) \cdot (m\bmod j)})

i=1nj=1m(nini)(mjmj)\sum_{i=1}^{n}\sum_{j=1}^{m}{(n-i\lfloor \frac{n}{i} \rfloor)(m-j\lfloor \frac{m}{j} \rfloor)}

i=1nj=1m(nmnjmjmini+ijnimj)\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)}

n2m2n2j=1mjmjm2i=1nini+i=1ninii=1mjmjn^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)(nmodi)(mmodi)\sum_{i=1}^{min(n, m)}{(n\bmod i)\cdot (m\bmod i)}

i=1min(n,m)(nini)(mimi)\sum_{i=1}^{min(n, m)}{(n - i\lfloor \frac{n}{i} \rfloor)(m - i\lfloor \frac{m}{i} \rfloor)}

i=1min(n,m)nmmininimi+i2nimi\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