1. 程式人生 > >[BZOJ1925][SDOI2010]地精部落(DP)

[BZOJ1925][SDOI2010]地精部落(DP)

裏的 pac bubuko 興趣 print space ima 工作 一段

技術分享圖片

題意

傳說很久以前,大地上居住著一種神秘的生物:地精。 地精喜歡住在連綿不絕的山脈中。具體地說,一座長度為 N 的山脈 H可分 為從左到右的 N 段,每段有一個獨一無二的高度 Hi,其中Hi是1到N 之間的正 整數。 如果一段山脈比所有與它相鄰的山脈都高,則這段山脈是一個山峰。位於邊 緣的山脈只有一段相鄰的山脈,其他都有兩段(即左邊和右邊)。 類似地,如果一段山脈比所有它相鄰的山脈都低,則這段山脈是一個山谷。 地精們有一個共同的愛好——飲酒,酒館可以設立在山谷之中。地精的酒館 不論白天黑夜總是人聲鼎沸,地精美酒的香味可以飄到方圓數裏的地方。 地精還是一種非常警覺的生物,他們在每座山峰上都可以設立瞭望臺,並輪 流擔當瞭望工作,以確保在第一時間得知外敵的入侵。 地精們希望這N 段山脈每段都可以修建瞭望臺或酒館的其中之一,只有滿足 這個條件的整座山脈才可能有地精居住。 現在你希望知道,長度為N 的可能有地精居住的山脈有多少種。兩座山脈A 和B不同當且僅當存在一個 i,使得 Ai≠Bi。由於這個數目可能很大,你只對它 除以P的余數感興趣。

思路

DP

但是思維難度大

借鑒別人的

bzoj限空間,要滾存

代碼

#include<bits/stdc++.h>
using namespace std;
const int N=4210;
int C[2][N],f[N],P,n;
int main()
{
    scanf("%d%d",&n,&P);
    C[0][0]=C[1][0]=f[0]=1;
    for(int i=1;i<=n;i++)
    for(int j=1;j<=i;j++)
    {
        if(j&1) (f[i]+=1ll*f[j-1
]*f[i-j]%P*C[(i-1)&1][j-1]%P)%=P; C[i&1][j]=(C[(i-1)&1][j]+C[(i-1)&1][j-1])%P; } printf("%d\n",2ll*f[n]%P); return 0; }

[BZOJ1925][SDOI2010]地精部落(DP)