BZOJ1925 SDOI2010 地精部落

2022-08-19 22:51:14 字數 1635 閱讀 1892

傳送門

求\(n\)的排列中有多少個波動數列.

波動數列是指對於數列中的每乙個數,他兩邊的數必須嚴格小於或大於自己.

\[n \leq 4200, mod \leq 1e9

\]首先我們必須要搞清楚3個性質

4 2 3 1 5

舉個栗子: 1 4 2 5 3 (用 6 - 每個數) 1是山谷,4是山峰,後面類推

5 2 4 1 3 這個數列也是波動的 ,且 5是山峰,2是山谷;

(以上**luogu)

那麼我們設\(dp[i][j]\)表示\(1\)到\(i\)的排列中, 當前數列首端為高度j的山峰的方案數.

考慮如果j,j - 1不相鄰, 那麼直接交換就可以.即\(dp[i][j - 1]\)

如果相鄰, 那麼顯然j - 1是山谷. 所以應用性質二,把山峰變成山谷,即:\(dp[i - 1][(i - 1 + 1) - (j - 1)] = dp[i - 1][i - j + 1]\)

所以答案為:\(dp[i][j] = dp[i][j - 1] + dp[i - 1][i - j + 1]\)

由於空間太小, 考慮滾動陣列優化.

codes

#includeusing namespace std;

#define rep(i, a, b) for(int i = (a), i##_end_ = (b); i <= i##_end_; ++i)

#define drep(i, a, b) for(int i = (a), i##_end_ = (b); i >= i##_end_; --i)

#define clar(a, b) memset((a), (b), sizeof(a))

#define debug(...) fprintf(stderr, __va_args__)

#define debug(s) debug("the massage in line %d, function %s: %s\n", __line__, __function__, s)

typedef long long ll;

typedef long double ld;

const int buf_size = (int)1e6 + 10;

struct fastio

inline char getchar()

inline void putchar(char ch)

inline int flush()

}io;

#define getchar io.getchar

#define putchar io.putchar

int read()

void write(int x)

void putstring(char s, char endchar = '\n')

#define maxn 4209

int n, p, dp[2][maxn];

namespace init

}namespace solve

}int main()

bzoj1925 Sdoi2010 地精部落

題目大意 求全排列中鋸齒狀排列的個數。首先進行打表暴力,會發現第乙個元素作為山峰和第乙個元素作為山谷,這兩種方案數是相等的,因此我們只需求出第乙個元素是山谷的方案數再乘2就是答案。做法一 f i 表示i的全排列,第乙個元素時山谷時,鋸齒狀排列的方案數。那麼考慮在i 1的乙個鋸齒狀排列中插入i這個數,...

bzoj1925 Sdoi2010 地精部落

傳送門 我們設f i j 表示前i個數,第i個數排名是j的方案總數。我們可以強制第1個數是山峰。然後我們可以將整個序列高度取反,得到其他的方案數。然後我們發現這樣做的時間複雜度是o n 3 的 加上字首和優化就是o n 2 了 var f array 0.1,0.5005 of longint n,...

bzoj1925 Sdoi2010 地精部落

傳說很久以前,大地上居住著一種神秘的生物 地精。地精喜歡住在連綿不絕的山脈中。具體地說,一座長度為n的山脈h可分為從左到右的n段,每段有乙個獨一無二的高度hi,其中hi是1到n之間的正整數。如果一段山脈比所有與它相鄰的山脈都高,則這段山脈是乙個山峰。位於邊緣的山脈只有一段相鄰的山脈,其他都有兩段 即...