Contest0226 -- 湖南2015省队集训

Hoodles!

斜率优化+平衡树

然而一看到就想到了cash,事实上这道题凸包上倍增就可以,写了个cdq跑得贼慢

Math!

找规律?

证明:

Help!

求$\sum_{n=1}^N \sum_{m=1}^M \sum_{k=0}^{m-1}\lfloor \frac{nk+x} m\rfloor$

分开计算每个部分:

可得答案:

最后反演,$O(n)$得答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <stdio.h>
#include <math.h>
#include <algorithm>
using namespace std;
const int N = 500005;
typedef long long ll;
const ll mod = 998244353;
ll n, m, ans, sum[N];
int p[N], tot, mu[N], vis[N];
void Euler() {
mu[1] = 1;
for (int i = 2; i <= 500000; i++) {
if (!vis[i]) p[++tot] = i, mu[i] = -1;
for (int j = 1; j <= tot && i * p[j] <= 500000; j++) {
int k = i * p[j];
vis[k] = 1;
if (i % p[j]) mu[k] = -mu[i];
else {
mu[k] = 0;
break;
}
}
}
for (int i = 1; i <= 500000; i++) mu[i] += mu[i - 1];
}
ll G(ll x, ll y) {
ll rt = 0, i, j;
for (i = 1; i <= x; i = j + 1){
j = min(x / (x / i), y / (y / i));
rt += (mu[j] - mu[i - 1]) * (x / i) % mod * (y / i) % mod;
rt %= mod;
}
return rt;
}
int main() {
int i, j, k;
double x;
scanf("%lld%lld%lf", &n, &m, &x);
ans = n * m % mod * (n - 1) % mod * (m - 1) % mod * 748683265 % mod - n * m % mod + mod;
ans %= mod;
if (n > m) swap(n, m);
Euler();
for (i = 1; i <= n; i++) sum[i] = (sum[i - 1] + i + 2 * i * (ll)(x / i) % mod) % mod;
for (i = 1; i <= n; i = j + 1) {
j = min(n / (n / i), m / (m / i));
ans += (sum[j] - sum[i - 1] + mod) % mod * G(n / i, m / i) % mod;
ans %= mod;
}
ans *= 499122177;//rev 2
ans %= mod;
printf("%lld", ans);
}