博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
BZOJ1044: [HAOI2008]木棍分割
阅读量:4965 次
发布时间:2019-06-12

本文共 2165 字,大约阅读时间需要 7 分钟。

【传送门:】


简要题意:

  给出n个数,求出最多分成m+1段的最长段的最小值,并且求出能分成最长段最小的情况数


题解:

  一道思维题(好吧,就是搞了我一晚上的题)

  首先最小值我们可以用二分来搞出来,二分最小值,然后从头开始,一直累加,如果当前累加值加上a[i]超过了二分出来的值的话,就新开一个段,并且把a[i]放在这个段的开头,最后如果分成的段小于等于m+1的话,就证明这个最小值是行得通的

  其实求最小值并不是难处,关键是怎么求情况数

  很容易想到设f[i][j]为到第i个数时分成j段的情况数

  设s[i]为$\sum_{j=1}^{i}a[j]$

  可以得到方程$$f[i][j]=\sum_{s[i]-s[k]<=d}(i>k)f[k][j-1]$$

  但是这样O(mn^2)肯定会T,而且空间也过大

  那么怎么优化呢?

  我们发现其实f[][j]只与f[][j-1]有关系,那么我们可以用滚动数组来优化空间

  然后其实a数组和s数组是保持不变的,也就是说对于i这个位置而言,往前面延伸,能延伸最前面的位置设为k[i],也就是当s[i]-s[k]<=d时,k[i]就表示为k的最小值

  那么我们就可以把方程转化为$$f[i][q]=\sum_{s[i]-s[k]<=d}(i>k)f[k][p]$$

  p表示上一次的状态,q表示现在要处理的状态

  其实我们看得出来可以用前缀和来得到$\sum_{s[i]-s[k]<=d}(i>k)f[k][p]$

  时间就可以优化到O(nm)了

  接下来是些小细节:对于一开始f[0][0]要等于1,因为后面的数有可能只分成一段,所以用来特判这种情况


参考代码:

#include
#include
#include
#include
using namespace std;int l[51000],m,n;int s[51000];int sum[51000];int f[2][51000];int k[51000];bool check(int d){ int dd=0;int mm=1; for(int i=1;i<=n;i++) { if(dd+l[i]>d) { dd=l[i]; if(dd>d) return false; mm++;if(mm>m) return false; } else dd+=l[i]; } return true;}int main(){ scanf("%d%d",&n,&m);m++; s[0]=0; for(int i=1;i<=n;i++) { scanf("%d",&l[i]); s[i]=s[i-1]+l[i]; } int l=1,r=s[n]; int d=0; while(l<=r) { int mid=(l+r)/2; if(check(mid)==true) { d=mid; r=mid-1; } else l=mid+1; } printf("%d ",d); memset(f,0,sizeof(f)); l=1;r=1; while(r<=n) { while(s[r]-s[l-1]>d) l++; k[r]=l; r++; } int p=0; int ans=0; f[0][0]=1; for(int i=1;i<=m;i++) { int q=1-p; sum[0]=f[p][0]; for(int j=1;j<=n;j++) sum[j]=(sum[j-1]+f[p][j])%10007; f[q][0]=0; for(int j=i;j<=n;j++) { int d; if(k[j]==1) d=sum[j-1]; else d=sum[j-1]-sum[k[j]-2]; f[q][j]=(d+10007)%10007; } ans=(ans+f[q][n])%10007; p=q; } printf("%d\n",(ans+10007)%10007); return 0;}

 

转载于:https://www.cnblogs.com/Never-mind/p/8117666.html

你可能感兴趣的文章
HTML-参考手册: 画布
查看>>
杂项:MIS
查看>>
Node.js:全局对象
查看>>
6、python中的字符串
查看>>
String、StringBuffer与StringBuilder之间区别
查看>>
bash中常见环境变量env、set、export 、declare与bash漏洞原理
查看>>
Vue.js 子组件的异步加载及其生命周期控制
查看>>
数据库表结构导出sql语句
查看>>
C++库(Thrift)
查看>>
第十五周助教小结
查看>>
P2260 [清华集训2012]模积和
查看>>
MD5加密工具类
查看>>
linux less命令详情
查看>>
Java框架之Mybatis(二)
查看>>
angular复选框式js树形菜单(二)
查看>>
java基础(第三章课后作业)04
查看>>
自定义ClassLoader
查看>>
用python发邮件实例
查看>>
Python基础-包
查看>>
oss文件删除策略
查看>>