日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

SDOI2010 地精部落

發布時間:2023/12/13 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 SDOI2010 地精部落 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目描述

傳說很久以前,大地上居住著一種神秘的生物:地精。

地精喜歡住在連綿不絕的山脈中。具體地說,一座長度為N的山脈H可分為從左到右的N段,每段有一個[b][u]獨一無二[/u][/b]的高度Hi,其中Hi是1到N之間的正整數。

如果一段山脈比所有與它相鄰的山脈都高,則這段山脈是一個山峰。位于邊緣的山脈只有一段相鄰的山脈,其他都有兩段(即左邊和右邊)。

類似地,如果一段山脈比所有它相鄰的山脈都低,則這段山脈是一個山谷。

地精們有一個共同的愛好——飲酒,酒館可以設立在山谷之中。地精的酒館不論白天黑夜總是人聲鼎沸,地精美酒的香味可以飄到方圓數里的地方。

地精還是一種非常警覺的生物,他們在每座山峰上都可以設立瞭望臺,并輪流擔當瞭望工作,以確保在第一時間得知外敵的入侵。

地精們希望這N段山脈每段都可以修建瞭望臺或酒館的其中之一,只有滿足這個條件的整座山脈才可能有地精居住。

現在你希望知道,長度為N的可能有地精居住的山脈有多少種。兩座山脈A和B不同當且僅當存在一個i,使得Ai≠Bi。由于這個數目可能很大,你只對它除以P的余數感興趣。

輸入輸出格式

輸入格式:

?

輸入文件goblin.in僅含一行,兩個正整數N, P。

?

輸出格式:

?

輸出文件goblin.out僅含一行,一個非負整數,表示你所求的答案對P取余之后的結果。

?

輸入輸出樣例

輸入樣例#1:
4 7 輸出樣例#1:
3

說明

說明:共有10種可能的山脈,它們是:

1[u]3[/u]2[u]4[/u] 1[u]4[/u]2[u]3[/u] [u]2[/u]1[u]4[/u]3 2[u]3[/u]1[u]4[/u] 2[u]4[/u]1[u]3[/u]

[u]3[/u]1[u]4[/u]2 [u]3[/u]2[u]4[/u]1 3[u]4[/u]1[u]2[/u] [u]4[/u]1[u]3[/u]2 [u]4[/u]2[u]3[/u]1

其中加下劃線的數位表示可以設立瞭望臺的山峰,其他表示可以設立酒館的山谷。

【數據規模和約定】

對于20%的數據,滿足N≤10;

對于40%的數據,滿足N≤18;

對于70%的數據,滿足N≤550;

對于100%的數據,滿足3≤N≤4200,P≤109。

?

題意:求波動序列的個數

首先,了解波動序列的對稱性

序列如果為 1 4 2 5 3

對稱序列為 5 2 4 1 3

如果原序列開始遞減,那么同n+1減每個數,就變成了遞減序列的對稱遞增序列

所以我們只需要求遞減序列,乘2就是總個數

dp[i][j] 表示 前i個數的排列中,第1個數為j,且開始遞減的序列個數

f[i][j] 表示 前i個數的排列中,第1個數為j,且開始遞增的序列個數

當第1個數是j時,后面可以填1,2,3,……j-1,j+1,j+2……n

把>j的每個數-1,就是1,2,3,……j-1,j,j+1,j+2……n-1

即變成了n-1的排列

如果開始遞減

當第1個數是j時,將>j的數全部-1,那么后面可以填的數就是一個n-1的排列

這個排列要求 第一個數<j,且開始遞增

即dp[i][j]= Σ f[i-1][k] ?k∈[1,j-1]

根據對稱性,dp[i][j]= Σdp[i-1][k] ?k∈[i-j+1,i-1]?

時間復雜度:O(n^3),空間復雜度:O(n^2)

使用前綴和優化,可以 優化到時間O(n^2),空間O(n)

?

沒有用前綴和優化的代碼:

#include<cstdio> #define N 4201 using namespace std; int n,p,ans; int dp[N][N],sum[N]; int main() {scanf("%d%d",&n,&p);for(int i=1;i<=n;i++) dp[1][i]=1;for(int i=2;i<=n;i++)for(int j=2;j<=i;j++)for(int k=i-j+1;k<=i-1;k++) dp[i][j]=(dp[i-1][k]+dp[i][j])%p;for(int i=1;i<=n;i++) ans=(ans+dp[n][i])%p;ans=ans*2%p;printf("%d",ans); }

?

前綴和優化AC代碼:

#include<cstdio> #include<cstring> #include<algorithm> #define N 4201 using namespace std; int n,p,ans; int dp[N],sum[N]; int main() {scanf("%d%d",&n,&p);for(int i=1;i<=n;i++) dp[i]=1;for(int j=1;j<=n;j++) sum[j]=(sum[j-1]+dp[j])%p;for(int i=2;i<=n;i++){dp[1]=0; for(int j=2;j<=i;j++) dp[j]=(sum[i-1]-sum[i-j]+p)%p;for(int j=i+1;j<=n;j++) dp[j]=0;for(int j=1;j<=n;j++) sum[j]=(sum[j-1]+dp[j])%p;}for(int i=1;i<=n;i++) ans=(ans+dp[i])%p;ans=ans*2%p;printf("%d",ans); }

?

轉載于:https://www.cnblogs.com/TheRoadToTheGold/p/7305170.html

總結

以上是生活随笔為你收集整理的SDOI2010 地精部落的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。