題解 [SDOI2010]地精部落

Chtholly

題目描述

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

輸入輸出格式

輸入格式
輸入文件goblin.in僅含一行,兩個正整數(shù)N, P。
輸出格式
輸出文件goblin.out僅含一行,一個非負整數(shù),表示你所求的答案對P取余之后的結(jié)果。

輸入輸出樣例

輸入樣例#1

4 7

輸出樣例#1

3

解題思路

定義狀態(tài)變量 f [ i ] [ j ] 表示序列長度為 i 時有 j 個數(shù)不符合要求時的方案數(shù),這里的“不符合要求”指的是后一個數(shù)大于前一個數(shù),例如1,2,3這樣的序列,3對于2來說定義為不符合要求,故最終答案應(yīng)該為 f [ n ] [ 0 ] * 2,因為這種狀態(tài)只考慮了一種情況,還有可能后一個數(shù)小于前一個數(shù)而不符合要求的情況
那么狀態(tài)轉(zhuǎn)移方程就很好想了,有以下三種情況可以轉(zhuǎn)移:

  • 考慮第 i + 1 個數(shù)插在了對其自身來說符合要求的位置,那么對當前已有的不符合要求的數(shù)的個數(shù)是沒有影響的,故轉(zhuǎn)移方程為:
    f [ i + 1 ] [ j ] += f [ i ] [ j ] ;
  • 考慮第 i + 1 個數(shù)插在了一個當前不符合要求的數(shù)之前,那么這個數(shù)在 i + 1 插入之后就符合要求了,故轉(zhuǎn)移方程為:
    f [ i + 1 ] [ j - 1 ] += f [ i ] [ j ] * j ;
  • 考慮第 i + 1 個數(shù)插在了當前已經(jīng)符合要求的數(shù)之前,那么在插入了 i + 1 之后就會再新增一個不符合要求的數(shù),故轉(zhuǎn)移方程應(yīng)為:
    f [ i + 1 ] [ j + 1 ] += f [ i ] [ j ] * ( i - j ) ;

最終的答案就是 f [ n ] [ 0 ] * 2
在代碼實現(xiàn)過程中需要注意的就是取模,在沒有別的什么了
下面是C++代碼

數(shù)據(jù)規(guī)模和約定

對于20%的數(shù)據(jù),滿足N≤10;
對于40%的數(shù)據(jù),滿足N≤18;
對于70%的數(shù)據(jù),滿足N≤550;
對于100%的數(shù)據(jù),滿足3≤N≤4200,P≤1e9。

C++代碼

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define rr register
using namespace std;

typedef long long LL;
const int maxn=4200+10;
LL n,m,p,ans;
LL f[maxn][maxn];

inline LL read(){//珂朵莉版快讀~~~
    int chtholly=0,willem=1;char c=getchar();
    while(c<'0' || c>'9'){if(c=='-')willem=-1;c=getchar();}
    while(c<='9' && c>='0'){chtholly=chtholly*10+(LL)(c-'0');c=getchar();}
    return chtholly*willem;
}

int main(){
    n=read(),p=read();
    f[1][0]=1;
    for(rr int i=1;i<=n;i++)for(int j=0;j<=i;j++){
        f[i+1][j]=(f[i+1][j]+f[i][j])%p;
        f[i+1][j-1]=(f[i+1][j-1]+f[i][j]*j%p)%p;
        f[i+1][j+1]=(f[i+1][j+1]+f[i][j]*(i-j)%p)%p;
    }
    ans=(f[n][0]<<1)%p;//位運算加速
    printf("%lld\n",ans);
    return 0;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 背景 一年多以前我在知乎上答了有關(guān)LeetCode的問題, 分享了一些自己做題目的經(jīng)驗。 張土汪:刷leetcod...
    土汪閱讀 12,927評論 0 33
  • 計算機二級C語言上機題庫(南開版) 1.m個人的成績存放在score數(shù)組中,請編寫函數(shù)fun,它的功能是:將低于平...
    MrSunbeam閱讀 6,621評論 1 42
  • 回溯算法 回溯法:也稱為試探法,它并不考慮問題規(guī)模的大小,而是從問題的最明顯的最小規(guī)模開始逐步求解出可能的答案,并...
    fredal閱讀 14,015評論 0 89
  • 自從進組以來,這一年又一個月過去,我發(fā)現(xiàn)自己再沒有學(xué)習(xí)的動力,整日在綜藝電視劇里休閑度日,那些過往的進取心,上進心...
    FM_C閱讀 148評論 0 0
  • 我們一天的快樂自由 就這樣白白地浪費掉了 我們一天的閑暇快樂 就這樣不忍直視 我是多么渴望著能與球相伴一生 過著一...
    半分微涼閱讀 197評論 2 2

友情鏈接更多精彩內(nèi)容