這道題是一道$dp$題,思維難度比較大。
題意:先定義波形陣列:滿足當$i$全為奇數或偶數時,$a[i]>a[i-1]$且$a[i]>a[i+1]$。
求$n$的全排列中有多少個符合波形陣列。
我們記錄狀態為$f[i][j][0/1]$,$i$為剩下$i$個數,$j$表示有$j-1$個數小於剛剛選擇的數,當第$3$個下標為$0$時,表示這是山谷,為$1$則說明是山頂。
推理知道$f[i][j][0]$能影響$f[i-1][j..i][1]$,$f[i][j][1]$能影響$f[i-1][1..j-1][0]$。
最後求$f[0][1][0]+f[0][1][1]$的值即可。
此時時間複雜度為$o(n^3)$,空間為$o(n^3)$。
但是過不了。。
考慮將轉移方程變化下,把刷表改成填表,就發現$f[i][j][1]=\sum_^jf[i+1][x][0]$,$f[i][j][0]=\sum_^f[i+1][x][1]$,然後又發現可以在填表的過程中順便求下$\sigma$,於是就優化到了$o(n^2)$。
而空間可以通過滾動陣列優化掉一維。
1 #include 23using
namespace
std;45
#define re register
6#define rep(i, a, b) for (re int i = a; i <= b; ++i)
7#define repd(i, a, b) for (re int i = a; i >= b; --i)
8#define maxx(a, b) a = max(a, b);
9#define minn(a, b) a = min(a, b);
10#define ll long long
11#define inf (1 << 30)
1213 inline int
read()
1920
const
int maxn = 4200 + 10;21
22int f[2][maxn][2], n, p, cur = 1;23
24int
main()
39 v = f[cur^1][i+2][1
];40 repd(j, i+1, 1
) 44}45
46 printf("
%d", (f[cur][1][0] + f[cur][1][1]) %p);
4748
return0;
49 }
這道題還可以用數學統計下手推方程。
SDOI2010 地精部落
求1 n的全排列數目,使得對於 i geq 3 a a 的大小關係與 a a 的大小關係不同 題目還有另外一種格式 求一種全排列,使得這個排列要麼滿足奇數項的高度比相鄰位置都大,要麼滿足偶數項的高度比相鄰位置都大.設 dp 表示用了前 i 個數字,a 1 j 且 a 1 a 2 時的方案數 有乙個神...
SDOI2010 地精部落
sdoi2010 地精部落 僅含一行,兩個正整數 n,p。僅含一行,乙個非負整數,表示你所求的答案對p取餘 之後的結果。4 7對於 20 的資料,滿足 n 10 對於 40 的資料,滿足 n 18 對於 70 的資料,滿足 n 550 對於 100 的資料,滿足 3 n 4200,p 109 我覺得...
SDOI2010 地精部落
傳說很久以前,大地上居住著一種神秘的生物 地精。地精喜歡住在連綿不絕的山脈中。具體地說,一座長度為n的山脈h可分為從左到右的n段,每段有乙個 b u 獨一無二 u b 的高度hi,其中hi是1到n之間的正整數。如果一段山脈比所有與它相鄰的山脈都高,則這段山脈是乙個山峰。位於邊緣的山脈只有一段相鄰的山...