[HAOI2009] 逆序對數列
阿新 • • 發佈:2018-08-24
can ostream 逆序對數 逆序 limits include limit 逆序對 ()
[HAOI2009] 逆序對數列
題目大意:求\([1,n]\)的自然數的排列中逆序對數為\(k\)的有多少.
這樣來DP
狀態:設\(f[i][j]\)為\(i\)個數,逆序對數為\(j\)的種類數目
- 轉移方程:\(f[i][j] = \sum \limits _{k=j-i+1}^{j}f[i-1][k]\),\(i\)時最多可以貢獻\(i-1\)對逆序對,也就是\(k\)最極限也就\(j-(i+1)\)
優化:前綴和即可
代碼
無優化
#include <iostream> #include <cstdio> const int Mod = 10000; int f[1005][1005]; int main(){ int n, k; scanf("%d %d", &n, &k); for(int i = 1; i <= n; ++i){ f[i][0] = 1; for(int j = 1; j <= k; ++j){ for(int q = std::max(j - i + 1, 0); q <= j; ++q){ f[i][j] = (f[i][j] + f[i - 1][q]) % Mod; } } } printf("%d\n", f[n][k]); return 0; }
優化
#include <iostream> #include <cstdio> const int Mod = 10000; int f[1005][1005], sum[1005]; int main(){ int n, k; scanf("%d %d", &n, &k); for(int i = 1; i <= n; ++i){ f[i][0] = 1; for(int q = 1; q <= k + 1; ++q){ sum[q] = (sum[q - 1] + f[i - 1][q - 1]) % Mod; }//更新前綴和,這裏的要註意下這個前綴和代表的比較特殊,不是普通的i到j是sum[i]-sum[j-1],得加1 for(int j = 1; j <= k; ++j){ f[i][j] = (sum[j + 1] - sum[j - i + 1] + Mod) % Mod; }//前綴和減去不能達到的 } printf("%d\n", f[n][k]); return 0; }
錯誤
- 先寫了一遍沒有優化的,日常忘記模數
- 但是因為\(j-i+1\)會小於\(0\),這是不被允許的
- \(std::max(j-i+1,1)\)不行,因為可以到\(0\),應該是\(std::max(j-i+1,1)\)
- 優化後因為有個相減再取模,忘記\(+Mod\)
[HAOI2009] 逆序對數列