洛谷 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;
}
posted @ 2025-01-05 21:01  syzyc  阅读(20)  评论(0)    收藏  举报