51nod 1201 整數劃分

2021-08-19 14:25:44 字數 1582 閱讀 9399

1201 整數劃分

基準時間限制:1 秒 空間限制:131072 kb 分值: 80 

難度:5級演算法題

將n分為若干個不同整數的和,有多少種不同的劃分方式,例如:n = 6, ,共4種。由於資料較大,輸出mod 10^9 + 7的結果即可。

input

輸入1個數n(1 <= n <= 50000)。
output

輸出劃分的數量mod 10^9 + 7。
input示例

6
output示例

4
題解:設dp[j][i]為取了前j個數,和為i的方案。要到達dp[j][i],有兩種方案:

第一種方案不增加新元素,即從dp[j][x]到達dp[j][i],為了保證不重複,故每個元素+1,即x = i - j;

第二種方案增加新元素,即從dp[j - 1][x]到達dp[j][i],為了保證dp[j - 1][x]與dp[j][x]不重複,我們發現dp[j][x]的元素都大1,故dp[j - 1][x]的新增元素為1,即x = i - j;

故轉移方程為:dp[j][i] = dp[j][i - j] + dp[j - 1][i - j]。此種方法時間空間複雜度都為o(n^2),超時超記憶體!

將n個數分成兩部分[0, (sqrt(n) + 0.9)),[(sqrt(n) + 0.9), n];

對於第一部分使用01背部。時間為o(n * (sqrt(n) + 0.9));

對於第二部分,每個元素至多取(sqrt(n) + 0.9)次,我們定義第一位是取j個元素,故我們可以使用轉移方程:dp[j][i] = dp[j][i - j] + dp[j - 1][i - j];注意,因為新增元素不是1而是(sqrt(n) + 0.9),故需要改變轉移方程,

最終的方程為:dp[j][i] = dp[j][i - j] + dp[j - 1][i - j - (sqrt(n) + 0.9) + 1];複雜度也為o(n * (sqrt(n) + 0.9));記錄乙個f1陣列,

f1[i] = ∑(1<=x<=(sqrt(n) + 0.9))dp[x][i];

最終乘起來即可!

ac**

#include #include #include #include #include #include #include #include #include typedef long long ll;

using namespace std;

const ll maxn = 55555, mod = 1e9 + 7;

ll dp[244][maxn] = , f[maxn] = , f1[maxn] = ;

int main()

dp[1][m] = 1;

for(ll i = m; i <= n; i++)

} ll ans = 0;

for(ll i = 0; i <= n; i++)

ans = (ans + f1[i] * f[n - i]) % mod;

printf("%lld\n", ans);

return 0;

}

51nod 1201 整數劃分

將n分為若干個不同整數的和,有多少種不同的劃分方式,例如 n 6,共4種。由於資料較大,輸出mod 10 9 7的結果即可。1 n 50000 直接一看就想到是一道最簡單揹包問題 但n 50000 然後我就直接上揹包,結果毫無疑問的超時,然後我的乙個夥伴在打二維揹包暴力時手抖打錯打出了正解 我們設f...

51nod 1201 整數劃分

dp轉移方程 dp i j dp i j j dp i j j 1 dp i j 表示將i分成j個不相等的數的個數。dp i j j dp i j 表示給原先的j個數各加一 dp i j j 1 dp i j 表示給原先的j 1的數加1,再附帶個1.因為不相等的數,所以n n 1 2 5e4 5,n...

51NOD 1201 整數劃分

題意 將n劃分成不同正整數的和的方案數。演算法 動態規劃 題解 暴力 f i j 只用前1.i的數字,總和為j的方案數 本質上是01揹包,前i個物體,總質量為j的方案數 f i j f i 1 j f i 1 j i 複雜度o n 2 優化 我們發現,因為要求數字不同,那麼數字最多也小於sqrt n...