1. 程式人生 > >BZOJ 1925: [Sdoi2010]地精部落

BZOJ 1925: [Sdoi2010]地精部落

spl else algo 入侵 ack 滿足 blog center pre

1925: [Sdoi2010]地精部落

Time Limit: 10 Sec Memory Limit: 64 MB

Description

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

Input

僅含一行,兩個正整數 N, P。

Output

僅含一行,一個非負整數,表示你所求的答案對P取余 之後的結果。

Sample Input

4 7

Sample Output

3

HINT


技術分享
對於 20%的數據,滿足 N≤10;
對於 40%的數據,滿足 N≤18;
對於 70%的數據,滿足 N≤550;
對於 100%的數據,滿足 3≤N≤4200,P≤109

這種序列的一般做法dp[i][j]前i為第i位為j的方案數,

這顯然是不行的。

我們需要把還剩那些記下來,

然而這還是不行的。

我們又發現它是一個排列,前面取的數是什麽我不關心,我只關心和下一個的大小關系,考慮剩下的和它的關系,我們能不能記下還剩比它小的數和比它大的數。

(⊙o⊙)…貌似可以了,再優化幾步就解了。

技術分享
 1 #include<iostream>
 2 #include<algorithm>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<cmath>
 6 #include<cstdlib>
 7 #include<vector>
 8 using namespace std;
 9 typedef long long ll;
10 typedef long double ld;
11 typedef pair<int
,int> pr; 12 const double pi=acos(-1); 13 #define rep(i,a,n) for(int i=a;i<=n;i++) 14 #define per(i,n,a) for(int i=n;i>=a;i--) 15 #define Rep(i,u) for(int i=head[u];i;i=Next[i]) 16 #define clr(a) memset(a,0,sizeof(a)) 17 #define pb push_back 18 #define mp make_pair 19 #define fi first 20 #define sc second 21 #define pq priority_queue 22 #define pqb priority_queue <int, vector<int>, less<int> > 23 #define pqs priority_queue <int, vector<int>, greater<int> > 24 #define vec vector 25 ld eps=1e-9; 26 ll pp=1000000007; 27 ll mo(ll a,ll pp){if(a>=0 && a<pp)return a;a%=pp;if(a<0)a+=pp;return a;} 28 ll powmod(ll a,ll b,ll pp){ll ans=1;for(;b;b>>=1,a=mo(a*a,pp))if(b&1)ans=mo(ans*a,pp);return ans;} 29 void fre() { freopen("c://test//input.in", "r", stdin); freopen("c://test//output.out", "w", stdout); } 30 //void add(int x,int y,int z){ v[++e]=y; next[e]=head[x]; head[x]=e; cost[e]=z; } 31 int dx[5]={0,-1,1,0,0},dy[5]={0,0,0,-1,1}; 32 ll read(){ ll ans=0; char last= ,ch=getchar(); 33 while(ch<0 || ch>9)last=ch,ch=getchar(); 34 while(ch>=0 && ch<=9)ans=ans*10+ch-0,ch=getchar(); 35 if(last==-)ans=-ans; return ans; 36 } 37 const int N=4205; 38 int dp[3][N]; 39 int main(){ 40 int n=read(),p=read(),sum=0; 41 if (n==1){ 42 puts("1"); 43 return 0; 44 } 45 for (int i=0;i<n;i++) dp[1][i]=1; 46 for (int i=2;i<=n;i++){ 47 if ((i&1)==0){ 48 sum=0; 49 for (int j=0;j<=n-i+1;j++) 50 sum=(sum+dp[(i-1)&1][j])%p,dp[(i)&1][j]=sum; 51 } else { 52 sum=0; 53 for (int j=n-i+1;j>=0;j--) 54 dp[(i)&1][j]=sum,sum=(sum+dp[(i-1)&1][j])%p; 55 } 56 } 57 printf("%d",(dp[n&1][0]*2)%p); 58 return 0; 59 }
View Code

BZOJ 1925: [Sdoi2010]地精部落