bzoj1044木棍分割
第一小问,显然二分一下就好,
然后有了答案了我们$dp$计算方案数
/************************************************************** Problem: 1044 User: zhangheran Language: C++ Result: Accepted Time:6844 ms Memory:3244 kb ****************************************************************/ #include<iostream> #include<cstdio> #include<algorithm> using namespace std; #define int long long const int mod=10007; int n,m; int l[50010],num[50010]; int ans;int ans2; int g[50010]; int f[50010]; int dp[50010]; bool check(long long x) { // if(x*m<num[n]) return false; // printf("%lld\n",x); int now=1;int len=0; for(int i=1;i<=n;i++) if(l[i]>x) return false; else if(len+l[i]>x) now++,len=l[i]; else len+=l[i]; return now<=m; } void work() { long long lef=1;long long rig=50000000; while(lef<=rig){ long long mid=lef+rig>>1; if(check(mid)) ans=mid,rig=mid-1; else lef=mid+1; // printf("%lld %lld %d\n",lef,rig,ans); } printf("%lld ",ans); return ; } signed main() { scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++) scanf("%lld",&l[i]),num[i]=num[i-1]+l[i]; m++; work(); int now=0; for(int i=1;i<=n;i++){ while(num[i]-num[now]>ans) now++; g[i]=now;} // printf("%d ",now); //for(int i=1;i<=n;i++) printf("%d ",g[i]); for(int i=0;i<=n;i++) dp[i]=1; for(int i=1;i<=m;i++){ for(int j=1;j<=n;j++) f[j]=(dp[j-1]-dp[g[j]-1])%mod;dp[0]=0; for(int j=1;j<=n;j++) dp[j]=f[j]+dp[j-1]; ans2=(ans2+f[n])%mod; } printf("%lld",ans2); return 0; }