[BZOJ1044] [HAOI2008]木棍分割

传送门

http://www.lydsy.com/JudgeOnline/problem.php?id=1044

题目大意

给定n段木棍,最多切m刀,并使最大段最小
1.询问最大段
2.询问方案数

题解

dp[i,j]:ij
显然 dp[i,j]=sum[i]sum[k]<=ans1dp[k,j1]
这是个 O(N2M)
这个是一段的转移,所以我们考虑用前缀和优化
并不好看是吧,我们稍微调整一下
dp[i,j]:ji
dp[i,j]=sum[j]sum[k]<=ansdp[i1,k]
这样前缀和就显然了吧~
sum[k]

uses math;
const
    maxn=50001;
var
    x,sum,s:array[-1..maxn]of longint;
    f:array[0..1,-1..maxn]of longint;
    i,j,k:longint;
    n,m,l,r,mid,ans,a,b,tt,t:longint;
function check(a:longint):longint;
var i,tt,tot:longint;
begin
    tt:=0; tot:=0;
    for i:=1 to n do
        if tt+x[i]>a
        then begin inc(tot); tt:=x[i]; end
        else inc(tt,x[i]);
    inc(tot);
    if tot>m+1 then exit(0) else exit(1);
end;

begin
    readln(n,m); sum[0]:=0; l:=0;
    for i:=1 to n do
        begin readln(x[i]); sum[i]:=sum[i-1]+x[i]; l:=max(l,x[i]); end;
    l:=0; r:=sum[n]; ans:=l;
    while l<=r do
        begin
            mid:=(l+r)>>1;
            if check(mid)=1
            then begin ans:=mid; r:=mid-1; end
            else l:=mid+1;
        end;
    write(ans,' ');
    f[0,0]:=1; a:=0; tt:=0;
    for i:=1 to m+1 do
        begin
            b:=a xor 1; s[0]:=0; s[-1]:=0;
            for j:=0 to n do f[b,j]:=0;
            for j:=0 to n do s[j]:=s[j-1]+f[a,j];
            t:=0;
            for j:=i to n do
                begin
                    while (t<=n+1)and(sum[t]<sum[j]-ans) do inc(t);
                    if t=n+2 then break;
                    f[b,j]:=(s[j-1]-s[t-1])mod 10007;
                end;
            tt:=(tt+f[b,n])mod 10007;
            a:=b;
        end;
    writeln(tt);
end.
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值