P2467 [SDOI2010] 地精部落 學習筆記

dolphina發表於2024-06-26

DP

顯然我固定第一個是峰,然後再乘以2就是答案,因為一個合法的反轉之後也是合法的而且谷峰顛倒了

發現如果設\(dp[i][j]\)表示前\(i\)個山脈,第\(i\)個山脈是高度\(j\)的答案,然後填第\(i\)個的時候不知道會不會重複,所以這個狀態掛了,重新找個狀態設設。

所以我們改變考慮物件,不考慮整個數列,只考慮已經填了的,我把已經填了的數的數列叫做\(S\),當我考慮到第\(i\)位的時候,這個\(dp[i][j]\)\(j\)表示它在裡面的相對位置,也就是排名。

現在就好搞多了,仍然我固定原數列下標奇數是峰,下標偶數是谷,下面給出DP過程。

對於偶數,\(dp[i][j]\)\(\sum\limits_{k=j}^{i-1}{dp[i-1][k]}\),因為我新的\(j\)加進來後,所有大於它的都要排名+1,所以原來我在第\(j\)個的,實際上是比它要大的

對於奇數,\(dp[i][j]\)\(\sum\limits_{k=1}^{j-1}{dp[i-1][k]}\)這個顯然,就是相對排名比\(j\)小,不說了

然後答案是對所有的\(dp[n][i]\)求和,沒了,程式碼:


顯然我固定第一個是峰,然後再乘以2就是答案,因為一個合法的反轉之後也是合法的而且谷峰顛倒了

所以我們改變考慮物件,不考慮整個數列,只考慮已經填了的,我把已經填了的數的數列叫做\(S\),當我考慮到第\(i\)位的時候,這個的\(j\)表示它在裡面的相對位置,也就是排名。

現在就好搞多了,仍然我固定原數列下標奇數是峰,下標偶數是谷,下面給出DP過程。

對於偶數,\(dp[i][j]\)\(我新的\)j\(加進來後,所有大於它的都要排名+1,所以原來我在第\)j$個的,實際上是比它要大的

對於奇數,\(dp[i][j]\)\(\sum\limits_{k=1}^{j-1}{dp[i-1][k]}\)這個顯然,就是相對排名比\(j\)小,不說了

然後答案是對所有的\(dp[n][i]\)求和,沒了,程式碼:
顯然我固定第一個是峰,然後再乘以2就是答案,因為一個合法的反轉之後也是合法的而且谷峰顛倒了

發現如果設\(dp[i][j]\)表示前\(i\)個山脈,第\(i\)個山脈是高度\(j\)的答案,然後填第\(i\)個的時候不知道會不會重複,所以這個狀態掛了,重新找個狀態設設。

所以我們改變考慮物件,不考慮整個數列,只考慮已經填了的,我把已經填了的數的數列叫做\(S\),當我考慮到第\(i\)位的時候,這個\(dp[i][j]\)\(j\)表示它在裡面的相對位置,也就是排名。

現在就好搞多了,仍然我固定原數列下標奇數是峰,下標偶數是谷,下面給出DP過程。

對於偶數,\(dp[i][j]\)\(\sum\limits_{k=j}^{i-1}{dp[i-5][k]}\),因為我新的\(j\)加進來後,所有大於它的都要排名+1,所以原來我在第\(j\)個的,實際上是比它要大的

對於奇數,\(dp[i][j]\)\(\sum\limits_{k=1}^{j-1}{dp[i-9][k]}\)這個顯然,就是相對排名比\(j\)小,不說了

然後答案是對所有的\(dp[n][i]\)求和,沒了,程式碼:
顯然我固定第一個是峰,然後再乘以2就是答案,因為一個合法的反轉之後也是合法的而且谷峰顛倒了

發現如果設\(dp[i][j]\)表示前\(i\)個山脈,第\(i\)個山脈是高度\(j\)的答案,然後填第\(i\)個的時候不知道會不會重複,所以這個狀態掛了,重新找個狀態設設。
標偶數是谷,下面給出DP過程。

對於偶數,\(dp[i][j]\)\(\sum\limits_{k=j}^{i-1}{dp[i-11][k]}\),因為我新的\(j\)加進來後,所有大於它的都要排名+1,所以原來我在第\(j\)個的,實際上是比它要大的

對於奇數,\(dp[i][j]\)\(\sum\limits_{k=1}^{j-1}{dp[i122][k]}\)這個顯然,就是相對排名比\(j\)小,不說了

然後答案是對所有的\(dp[n][i]\)求和,沒了,程式碼:
顯然我固定第一個是峰,然後再乘以2就是答案,因為一個合法的反轉之後也是合法的而且谷峰顛倒了

發現如果設\(dp[i][j]\)表示前\(i\)個山脈,第\(i\)個山脈是高度是谷,下面給出DP過程。

對於偶數,\(dp[i][j]\)\(\sum\limits_{k=j}^{i-1}{dp[i-1][k]}\),因為我新的\(j\)加進來後,所有大於它的都要排名+1,所以原來我在第\(j\)個的,實際上是比它要大的

對於奇數,\(dp[i][j]\)\(\sum\limits_{k=1}^{j-1}{dp[i-1][k]}\)這個顯然,就是相對排名比\(j\)小,不說了

然後答案是對所有的\(dp[n][i]\)求和,沒了,程式碼:

#include<bits/stdc++.h>
#define vd void 
int gi(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
int n,mod;
template<class Ta,class Tb>vd inc(Ta&a,Tb b){a=a+b>=mod?a+b-mod:a+b;}
template<class Ta,class Tb>int sub(Ta&a,Tb b){return a>=b?a-b:a+mod-b;}
int dp[4201][4201],s[4201];
int main(){
	n=gi(),mod=gi();
	for(int i=1;i<=n;i++)dp[1][i]=1,s[i]=s[i-1]+1;
	for(int i=2;i<=n;i++){
		for(int j=1;j<=i;j++){
			if(i&1)dp[i][j]=s[j-1]%mod;
			else dp[i][j]=sub(s[i-1],s[j-1]);
		}
		for(int j=1;j<=i;j++)s[j]=(s[j-1]+dp[i][j])%mod;
	}
	printf("%lld\n",s[n]*2%mod);
	return 0;
}

還有一份

#include<bits/stdc++.h>
#define vd void 
int gi(){
	char c;int x=0,f=0;
	while(!isdigit(c=getchar()))f|=(c=='-');
	while(isdigit(c))x=(x*10)+(c^48),c=getchar();
	return f?-x:x;
}
int n,mod;
template<class Ta,class Tb>vd inc(Ta&a,Tb b){a=a+b>=mod?a+b-mod:a+b;}
template<class Ta,class Tb>int sub(Ta&a,Tb b){return a>=b?a-b:a+mod-b;}
int dp[4201][4201],s[4201];
int main(){
	n=gi(),mod=gi();
	for(int i=1;i<=n;i++)dp[1][i]=1,s[i]=s[i-1]+1;
	for(int i=2;i<=n;i++){
		for(int j=1;j<=i;j++){
			if(i&1)dp[i][j]=s[j-1]%mod;
			else dp[i][j]=sub(s[i-1],s[j-1]);
		}
		for(int j=1;j<=i;j++)s[j]=(s[j-1]+dp[i][j])%mod;
	}
	printf("%lld\n",s[n]*2%mod);
	return 0;
}

相關文章