# bzoj1044

f[i,j]表示到第i根木棒切了j刀满足最长段小于等于ans的方案数

1 const mo=10007;
2 var f:array[0..1,0..50010] of longint;
3     sum,s,a,b:array[0..50010] of longint;
4     p,l,r,mid,n,m,i,j,t,ans:longint;
5
6 function check(s:longint):boolean;
7   var t,len,i:longint;
8   begin
9     t:=0;
10     len:=0;
11     p:=0;
12     for i:=1 to n do
13       if len+a[i]>s then
14       begin
15         inc(t);
16         if t>m then exit(false);
17         if len>p then p:=len;
18         len:=a[i];
19       end
20       else len:=len+a[i];
21     if len>p then p:=len;
22     exit(true);
23   end;
24 begin
26   for i:=1 to n do
27   begin
29     sum[i]:=sum[i-1]+a[i];
30     if l<a[i] then l:=a[i];
31   end;
32   r:=sum[i];
33   while l<=r do     //二分答案
34   begin
35     mid:=(l+r) shr 1;
36     if check(mid) then
37     begin
38       ans:=p;
39       r:=p-1;
40     end
41     else l:=mid+1;
42   end;
43   for i:=1 to n do
44     if sum[i]<=ans then f[0,i]:=1 else break;
45   j:=0;
46   for i:=1 to n do  //预处理
47   begin
48     while sum[i]-sum[j]>ans do inc(j);
49     b[i]:=j;
50   end;
51   p:=0;
52   t:=f[p,n];
53   for i:=1 to m do
54   begin
55     p:=1-p;
56     fillchar(s,sizeof(s),0);
57     for j:=1 to n do
58     begin
59       if b[j]-1>0 then r:=b[j]-1 else r:=0; //小细节
60       f[p,j]:=(s[j-1]-s[r]+mo) mod mo;
61       s[j]:=(s[j-1]+f[1-p,j]) mod mo;
62     end;
63     t:=(t+f[p,n]) mod mo;
64   end;
65   writeln(ans,' ',t);
66 end.
View Code

posted on 2014-05-15 13:26  acphile  阅读(87)  评论(0编辑  收藏