题解:P11504 [NordicOI 2018] French Fries
感谢镜像赛工作人员 @沉石鱼惊旋 提供官方题解。
以下设
考虑在
预处理
观察杨辉三角,我们发现两边的数比起中间是非常小的。我们可以设一个宽度
直接暴力考虑每个放薯条的位置对两边
进一步观察操作性质。发现
考虑将
由于每一段最大值不超过上一段的
再来分析误差,由于
时间复杂度
#include <iostream>
#include <cmath>
using namespace std;
const int W = 1e5, kW = W + 5;
const int V = 1e7 + W * 2, kV = V + 5;
const int kM = 5e7 + 5;
const int kN = 3e5 + 5;
const double D = 1.25;
const int L = 1000;
int n, m, a[kN];
double g, fac[kM], mp[kV], dif[kW];
int len, l[L], r[L];
double v[L];
double C (int n, int m) {
return fac[n] - fac[m] - fac[n - m];
}
int main () {
cin.tie(0)->sync_with_stdio(0);
cin >> n >> m >> g;
fac[0] = 0;
for (int i = 1; i <= m; ++i)
fac[i] = fac[i - 1] + log2(i);
for (int i = 1; i <= n; ++i)
cin >> a[i], a[i] += W;
for (int i = 0; i <= min(m, W); ++i) {
if ((i ^ m) & 1) continue;
int c = (i + m) >> 1;
double p = C(m, c) - m, v = 0;
if (p >= -60) v = pow(2, p);
dif[i] = v;
}
double mx, mi;
for (int o = m & 1, tl, tr, i = o; i <= W + 2; i += 2) {
if (dif[i] * D < mx || i == W + 2 || i == o) {
if (i != o) {
++len, l[len] = tl, r[len] = tr;
::v[len] = sqrt(mx * mi);
}
tl = tr = i, mx = mi = dif[i];
}
else {
tr = i, mi = dif[i];
}
}
auto add = [&](int l, int r, double x) -> void {
mp[l] += x, mp[r + 2] -= x;
};
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= len; ++j) {
add(a[i] - r[j], a[i] - l[j], v[j]);
add(a[i] + l[j], a[i] + r[j], v[j]);
}
}
for (int i = 2; i < V; ++i)
mp[i] += mp[i - 2];
int ans = 0;
for (int i = 0; i < V; ++i)
ans += mp[i] >= g;
cout << ans << '\n';
return 0;
}