洛谷 P2511 [HAOI2008] 木棍分割
第一问很简单,第二问 \(dp\)。
(真是哪都能混个 \(dp\))
#include <bits/stdc++.h>
using namespace std;
int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}
return x * f;
}
const int maxn = 5e4 + 7;
const int inf = 0x3f3f3f3f;
const int mod = 10007;
int n, m;
int len[maxn], sl[maxn];
int dp[maxn];
int sdp[maxn];
int pos[maxn];
int sol(int x) {
int k = 0;
for (int i = 1; i <= n; ++i)
for (; k < i; ++k)
if (sl[i] - sl[k] <= x) {
pos[i] = k;
break;
}
for (int i = 1; i <= n; ++i) dp[i] = (sl[i] <= x);
for (int i = 1; i <= n; ++i) sdp[i] = (sdp[i - 1] + dp[i]) % mod;
int res = sl[n] <= x;
for (int i = 2; i <= m + 1; ++i) {
for (int j = 1; j <= n; ++j) {
dp[j] = sdp[j - 1];
if (pos[j]) dp[j] = ((dp[j] - sdp[pos[j] - 1]) % mod + mod) % mod;
}
for (int j = 1; j <= n; ++j)
sdp[j] = (sdp[j - 1] + dp[j]) % mod;
res = (res + dp[n]) % mod;
}
return res;
}
bool check(int x) {
int sum = 0, cnt = 0;
for (int i = 1; i <= n; ++i)
if (sum + len[i] <= x) sum += len[i];
else ++cnt, sum = len[i];
return cnt <= m;
}
int main() {
n = read(), m = read();
int l = 0, r = 0, mid = 0, ans = 0;
for (int i = 1; i <= n; ++i) {
len[i] = read();
sl[i] = sl[i - 1] + len[i];
l = max(l, len[i]);
}
r = sl[n];
while (l <= r) {
mid = (l + r) >> 1;
if (check(mid)) ans = mid, r = mid - 1;
else l = mid + 1;
}
printf("%d %d\n", ans, sol(ans));
return 0;
}

浙公网安备 33010602011771号