HAOI2008 木棍分割

2022-05-31 18:39:13 字數 1398 閱讀 4285

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處切一刀 這樣就不會對後面的狀態產生影響 狀態轉移的方程即是當前分界線列舉上一條分界線在 上一條分界線與當前線之間如果相差不超過之前二分出來的答案,就可以...