僅含一行,兩個正整數 n, p。
僅含一行,乙個非負整數,表示你所求的答案對 p 取餘 之後的結果。
input
4 7output
3對於 20%的資料,滿足 n≤10;
對於 40%的資料,滿足 n≤18;
對於 70%的資料,滿足 n≤550;
對於 100%的資料,滿足 3≤n≤4200,p≤10 9
題意即為求用n個數構成波動序列的方案數。
考慮波動序列有如下性質:
那麼,根據這些性質,我們可以設如下狀態:\(f[i][j]\)表示用了1~i的數,第一項為j的方案數。由於性質2,第一項為山峰對稱一下就可以得到第一項為山谷的方案,因此不妨設j為山峰,最後乘2即可。
下面討論轉移。由性質1,當j與j-1不相鄰時,\(f[i][j]=f[i][j-1]\)。當j-1與j相鄰時,j-1只能為山谷且位於第2位。後面的取值範圍是\([1,j-1]\)和\([j+1,i]\)。同理,第一位為山谷的方案數可以通過性質3由山峰的方案推出,接下來只需要處理值域有空缺的問題。其實我們關心的只是相對的高矮,將區間\([j+1,i]\)整體減一併不影響答案。因此,相當於求用i-1個數0其中第j-1為第一位且為山谷的方案,為\(f[i-1][(i-1+1)-(j-1)]=f[i-1][i-j+1]\)。狀態轉移方程如下:
\[f[i][j]=f[i][j-1]+f[i-1][i-j+1]
\]最後答案為
\[ans=\sum_^f[n][i]
\]注意用滾動陣列優化空間。初始值因為1不可能作為山峰,要從2開始。
#include #include #include #define n 4202
using namespace std;
int n,p,i,j,f[2][n],x;
int main()
int ans=0;
for(i=2;i<=n;i++) ans=(ans+f[x][i])%p;
cout
}
地精部落 dp
description input 僅含一行,兩個正整數 n,p。output 僅含一行,乙個非負整數,表示你所求的答案對p取餘 之後的結果。sample input 4 7sample output 3hint 對於 20 的資料,滿足 n 10 對於 40 的資料,滿足 n 18 對於 70 的...
地精部落 題解
題目描述 輸入格式 僅含一行,兩個正整數 n,p。輸出格式 僅含一行,乙個非負整數,表示你所求的答案對p取餘 之後的結果。樣例樣例輸入 4 7樣例輸出 3資料範圍與提示 對於 20 的資料,滿足 n 10 對於 40 的資料,滿足 n 18 對於 70 的資料,滿足 n 550 對於 100 的資料...
BZOJ1925 地精部落
題目描述 輸入格式 僅含一行,兩個正整數 n,p。輸出格式 僅含一行,乙個非負整數,表示你所求的答案對p取餘之後的結果。樣例樣例輸入 4 7樣例輸出 3資料範圍與提示 對於 20 的資料,滿足 n 10 對於 40 的資料,滿足 n 18 對於 70 的資料,滿足 n 550 對於 100 的資料,...