[HAOI2008]木棍分割

本文介绍了一种结合二分搜索、贪心算法和动态规划的算法,用于解决将木棍分组的问题。首先通过二分搜索找到最优长度,然后使用动态规划计算在不超过该长度限制下,将木棍分为指定数量组的方法总数。算法通过前缀和优化了复杂度。

题解

第一问应该一眼就可以看出二分+贪心

问题是第二问。

可以想到\(dp\)

\(f[i][j]\)表示前i个木棍,分成j份, 每一份都不超过ans1的方案数

\(f_{i,j} =\sum_{k=x}^{i-1} f_{k,j-1}\)
\(( 第z位到第i位可以作为一段, x为最小的z )\)
显然\(x\)满足单调,可以\(O(n)\)求出

对于上面的dp,前缀和 就可以满足复杂度了

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register

using namespace std;

inline int gi() {
    RG int x = 0; RG char c = getchar(); bool f = 0;
    while (c != '-' && (c < '0' || c > '9')) c = getchar();
    if (c == '-') c = getchar(), f = 1;
    while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
    return f ? -x : x;
}

const int N = 50010, Mod = 10007;

int n, m, L[N];

bool check(int x) {
    int cnt = 0, s = 0;
    for (int i = 1; i <= n; i++) {
        if (L[i] > x) return 0;
        if (L[i] + s <= x) s += L[i];
        else cnt++, s = L[i];
    }   
    return cnt <= m;
}

int f[N], g[N], lf[N];

int main() {
    //freopen(".in", "r", stdin);
    //freopen(".out", "w", stdout);
    n = gi(), m = gi();
    int l = 0, r = 0;
    for (int i = 1; i <= n; i++) L[i] = gi(), r += L[i];
    while (l <= r) {
        int mid = (l + r) >> 1;
        if (check(mid)) r = mid-1;
        else l = mid+1;
    }
    int ans1 = r+1, ans2 = 0;
    int s = 0, w = 0;
    m++;
    s = L[1];
    for (int i = 2; i <= n; i++) {
        while (s+L[i] > ans1) s -= L[++w];
        s += L[i];
        lf[i] = w;
    }
    for (int i = 0; i <= n; i++)
        g[i] = 1;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= n; j++)
            f[j] = (g[j-1]-g[lf[j]-1]+Mod)%Mod;
        g[0] = 0;
        for (int j = 1; j <= n; j++)
            g[j] = (g[j-1]+f[j]) % Mod;
        ans2 = (f[n]+ans2) % Mod;
    }
    printf("%d %d\n", ans1, ans2);
    return 0;
}

转载于:https://www.cnblogs.com/zzy2005/p/10123746.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值