#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define rep(i,x,y) for(int i=(x);i<=(y);i++)
#define repl(i,x,y) for(int i=(x);i<(y);i++)
#define repd(i,x,y) for(int i=(x);i>=(y);i--)
using namespace std;
const int N=5e4+5;
const int Mod=1e4+7;
int n,m,mlen,len[N],sum[N],f[N][2];
inline int read() {
int x=0;char ch=getchar();bool f=0;
while(ch>'9'||ch<'0'){if(ch=='-')f=1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return f?-x:x;
}
inline int sub(int x,int y) { return x-y<0?x-y+Mod:x-y;}
inline int add(int x,int y) { return x+y>=Mod?x+y-Mod:x+y;}
bool check(int x) {
if(x<mlen) return false;
int tot=0,cnt=0;
rep(i,1,n) {
if(tot+len[i]>x) {
if(++cnt>m) return false;tot=0;
}
tot+=len[i];
}
return true;
}
int main() {
n=read(),m=read();
rep(i,1,n) {
len[i]=read();
sum[i]=sum[i-1]+len[i];mlen=max(mlen,len[i]);
}
int l=0,r=sum[n];
while(l<=r) {
int mid=l+r>>1;
if(check(mid)) r=mid-1;
else l=mid+1;
}
int ans1=l,ans2=0,cur=0;
rep(i,0,m) {
int id=1,tot=0;
rep(j,1,n) {
if(i==0) {
if(sum[j]<=ans1) f[j][0]=1;
else f[j][cur]=0;
} else {
while(id<j&&sum[j]-sum[id]>ans1) {
tot=sub(tot,f[id][cur^1]);++id;
}
f[j][cur]=tot;
}
tot=add(tot,f[j][cur^1]);
}
ans2=add(ans2,f[n][cur]);cur^=1;
}
printf("%d %d",ans1,ans2);
return 0;
}
BZOJ P1044 [HAOI2008]木棍分割【二分答案】【动态规划】
猜你喜欢
转载自blog.csdn.net/yanzhenhuai/article/details/82762138
今日推荐
周排行