BZOJ1044 [HAOI2008]木棍分割 【二分+Dp】
1044: [HAOI2008]木棍分割
Time Limit: 10 Sec Memory Limit: 162 MB
Submit: 4281 Solved: 1644
[Submit][Status][Discuss]
Description
有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连
接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少种砍的方法使得总长
度最大的一段长度最小. 并将结果mod 10007。。。
Input
输入文件第一行有2个数n,m.接下来n行每行一个正整数Li,表示第i根木棍的长度.n<=50000,0<=m<=min(n-1,10
00),1<=Li<=1000.
Output
输出有2个数, 第一个数是总长度最大的一段的长度最小值, 第二个数是有多少种砍的方法使得满足条件.
Sample Input
1
1
10
Sample Output
HINT
两种砍的方法: (1)(1)(10)和(1 1)(10)
显然我们可以二分算出第一问
算出第一问后,我们就可以dp求方案数了
设f[i][j]表示前i个木棒割j刀的方案数
则f[i][j] = ∑f[k][j - 1] 【k < i 且 sum[i] - sum[k] <= mx】
但这样做会爆
首先我们可以滚动数组,空间不爆了
其次我们会发现sum是递增的,也就是说k可以k + 1 ~ i - 1一定都可以,我们每次维护一次f的前缀和就可以加速了
【注意:取模过程中涉及减法,最后答案输出时要取回正数】
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = head[u]; k != -1; k = edge[k].next)
using namespace std;
const int maxn = 50005,maxm = 1005,INF = 1000000000,P = 10007;
inline int RD(){
int out = 0,flag = 1; char c = getchar();
while (c < 48 || c > 57) {if (c == '-') flag = -1; c = getchar();}
while (c >= 48 && c <= 57) {out = (out << 1) + (out << 3) + c - '0'; c = getchar();}
return out * flag;
}
int n,m,f[2][maxn],A[maxn],sum[maxn],S[maxn],mx = 0,Sum = 0,ans = 0;
bool check(int M){
if (mx > M) return false;
int cnt = 0,tot = 0;
for (int i = 1; i <= n; i++){
if (tot + A[i] > M) cnt++,tot = 0;
tot += A[i];
if (cnt > m) return false;
}
return true;
}
int main(){
n = RD(); m = RD();
REP(i,n) A[i] = RD(),sum[i] = sum[i - 1] + A[i],mx = max(mx,A[i]);
int l = 1,r = sum[n],mid;
while (l < r){
mid = l + r >> 1;
if (check(mid)) r = mid;
else l = mid + 1;
}
cout<<(mx = l)<<' ';
f[0][0] = 1;
for (int k = 0,p = 0; k <= m; k++){
S[0] = f[p][0];
REP(i,n) S[i] = (S[i - 1] + f[p][i]) % P;
p ^= 1; int pos = 0;
f[p][0] = 0;
for (int i = 1; i <= n; i++){
/*
for (int j = i - 1; j > 0; j--)
if (sum[i] - sum[j] <= mx)
f[p][i] = (f[p][i] + f[p ^ 1][j]) % P;
else break;*/
while (sum[i] - sum[pos] > mx) pos++;
f[p][i] = (S[i - 1] - (pos ? S[pos - 1] : 0)) % P;
}
ans = (ans + f[p][n]) % P;
}
cout<<(ans + P) % P<<endl;
return 0;
}
BZOJ1044 [HAOI2008]木棍分割 【二分+Dp】的更多相关文章
- bzoj1044: [HAOI2008]木棍分割 二分+dp
有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且输出有多少 ...
- [BZOJ1044][HAOI2008]木棍分割 二分+贪心+dp+前缀和优化
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 4112 Solved: 1577 [Submit][St ...
- 【bzoj1044】[HAOI2008]木棍分割 二分+dp
题目描述 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长度最小, 并且 ...
- Luogu P2511 [HAOI2008]木棍分割 二分+DP
思路:二分+DP 提交:3次 错因:二分写萎了,$cnt$记录段数但没有初始化成$1$,$m$切的次数没有$+1$ 思路: 先二分答案,不提: 然后有个很$naive$的$DP$: 设$f[i][j] ...
- [bzoj1044][HAOI2008][木棍分割] (二分+贪心+dp+队列优化)
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...
- [BZOJ1044][HAOI2008]木棍分割 二分 + 单调队列优化dp + 滚动数组优化dp
Description 有n根木棍, 第i根木棍的长度为Li,n根木棍依次连结了一起, 总共有n-1个连接处. 现在允许你最多砍断m个连接处, 砍完后n根木棍被分成了很多段,要求满足总长度最大的一段长 ...
- BZOJ 1044: [HAOI2008]木棍分割(二分答案 + dp)
第一问可以二分答案,然后贪心来判断. 第二问dp, dp[i][j] = sigma(dp[k][j - 1]) (1 <= k <i, sum[i] - sum[k] <= ans ...
- bzoj1044[HAOI2008]木棍分割 单调队列优化dp
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4314 Solved: 1664[Submit][Stat ...
- BZOJ1044: [HAOI2008]木棍分割
1044: [HAOI2008]木棍分割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1580 Solved: 567[Submit][Statu ...
随机推荐
- 【UE4】二十六、Look at camera 蓝图
如图,把BP_Cube替换为你需要的对象(如3DUI等)即可.
- Django学习之天气调查实例(3):部署静态文件CSS、JS、images等(部署环境基于Ubuntu)
在设计登录界面时,采用了网上下载的登录模板,漂亮,简易.但是在测试和部署时,发现原来模板中采用的js文件和css文件,却着实让我折腾了好几天. 在以往的网页设计中,一般只要把测试站点开启后,网页中的静 ...
- java doc 编写
总而言之,我觉得有用的是: @see 只要敲了@see 然后会自动写你的类名的,很方便.# 去连接字段 {@link } 只要敲了{@link } 然后会自动写你的类名的,很方便.# 去连接字段 如果 ...
- 关于实现mybatis order by 排序传递参数实现 问题记录
一 问题场景:本人项目纯纯的后端系统 并且项目前端采用纯纯的原生js 实现 1)表格 通过查询列表数据放入到域中 前段采用 for循环的方式实现遍历生成列表 2)分页实现本人是公司内部自定 ...
- PowerDesigner 使用记录
使用PowerDesigner 16.5 设计数据库表结构的操作过程: 第一步:打开PowerDesigner工具 第二步:创建一个新的数据模型,选择 File -> New Model -&g ...
- 自动化测试--封装getDriver的方法
在自动化测试的时候,通常都会把最常用的功能封装起来,实现通用性. 该篇博客是实现了getDriver方法的封装. 第一次封装的时候,是使用的传参. @Parameters(value = {" ...
- Linux系统安装jdk后出现无法执行binary 文件的错误解决
这是由于jdk版本的问题,针对Linux系统,Oracle提供了 ARM 的32jdk和64位jdk , 但是也提供了类似这样jdk-8u191-linux-i586.tar.gz32或64位的jdk ...
- Linux 进程--父进程查询子进程的退出状态
僵尸进程 当一个子进程先于父进程结束运行时,它与其父进程之间的关联还会保持到父进程也正常地结束运行,或者父进程调用了wait才告终止. 子进程退出时,内核将子进程置为僵尸状态,这个进程称为僵尸进程,它 ...
- LeetCode - 67. Add Binary(4ms)
Given two binary strings, return their sum (also a binary string). The input strings are both non-em ...
- 《Deep Learning》第二章 线性代数 笔记
第二章 线性代数 2.1 名词 标量(scalar).向量(vector).矩阵(matrix).张量(tensor) 2.2 矩阵和向量相乘 1. 正常矩阵乘法: 2. 向量点积: 3. Hadam ...