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,1000),1<=li<=1000.
output
輸出有2個數, 第乙個數是總長度最大的一段的長度最小值, 第二個數是有多少種砍的方法使得滿足條件.
sample input
3 21110
sample output
10 2
hint
兩種砍的方法: (1)(1)(10)和(1 1)(10)
第一問二分答案即可
考慮一下第二問的做法,設\(f[i][j]\)表示前\(j\)個分成\(i\)塊的方案數,因此有
\(f[i][j]=\sum f[i-1][k](sumv[j]-sumv[k]\leqslant max)\)
其中,\(sumv\)是長度的字首和,max是第一問的答案,\(\sum f[i-1][k]\)可以用字首和+單調佇列,\(f\)陣列可以用滾動進行優化,空間複雜度為\(o(n)\),時間複雜度為\(o(nm)\)
/*program from wolfycz*/
#include#include#include#include#include#define inf 0x7f7f7f7f
using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline int read()
inline void print(int x)
const int n=5e4,p=10007;
int val[n+10];
int n,m,limit;
namespace get_ans
return 1;
} int main()
return res;
}};namespace dp_solve
ans=(ans+f[i&1][n])%p;
} printf("%d %d\n",res,(ans+p)%p);
}};int main()
木棍分割 HAOI2008
有n根木棍,第i根木棍的長度為li,n根木棍依次鏈結了一起,總共有n 1個連線處.現在允許你最多砍斷m個連 接處,砍完後n根木棍被分成了很多段,要求滿足總長度最大的一段長度最小,並且輸出有多少種砍的方法使得總長 度最大的一段長度最小.並將結果mod 10007。輸入檔案第一行有2個數n,m.接下來n...
HAOI2008 木棍分割
沒寫過幾道的字首和優化 dp 第一問是小學生難度的二分 第二問就直接 dp 了 設 dp i j 表示當前分割點在 i 之後,前面一共分割了 j 段的方案數 利用字首和單調性,通過二分預處理出每乙個點往前能擴充套件到的最大位置,之後字首和優化就可以啦 但是發現這個樣子空間會炸,而這個樣子還沒有辦法滾...
題解 HAOI2008木棍分割
對於這道題目的兩問,第一問直接二分答案求出最短長度。關鍵在於第二問應當如何求 建立dp方程,dp i j 代表到第i個分界線,切了j次 強制在第i處切一刀 這樣就不會對後面的狀態產生影響 狀態轉移的方程即是當前分界線列舉上一條分界線在 上一條分界線與當前線之間如果相差不超過之前二分出來的答案,就可以...