转载请注明出处:http://blog.csdn.net/vmurder/article/details/42921155
第一问裸二分,第二问乱搞。
f[i][j]表示用掉i次机会,到j时合法的方案数。
代码:
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 50100 #define mod 10007 #define inf 0x3f3f3f3f using namespace std; int sk[N],sum[N],n,m; bool check(int mid) { int use=0,i,j,len=0; for(i=1;i<=n;i++) { len+=sk[i]; if(len+sk[i+1]>mid)use++,len=0; } if(use>m)return 0; else return 1; } int f[2][N]; int now,last; int main() { freopen("test.in","r",stdin); int i,j,k; int l=0,r=0,mid,ans; scanf("%d%d",&n,&m); for(i=1;i<=n;i++){ scanf("%d",&sk[i]); sum[i]=sum[i-1]+sk[i]; l=max(l,sk[i]),r+=sk[i]; } while(l<r) { if(r-l<=3) { for(i=r;i>=l;i--)if(check(i))ans=i; break; } mid=l+r>>1; if(check(mid))r=mid; else l=mid+1; } printf("%d ",mid=ans),ans=0; f[now=1][0]=1; int top; for(i=1;i<=m+1;i++) { now^=1,last^=1; k=0,top=i-2; for(j=i;j<=n;j++) { k+=f[last][j-1],k%=mod; while(sum[j]-sum[top+1]>mid) { k-=f[last][++top]; if(k<0)k+=mod; } f[now][j]=k; } ans+=f[now][n],ans%=mod; } printf("%d\n",ans); return 0; }
时间: 2024-10-13 15:07:25