藍橋杯模擬賽 擺動陣列的一種解法

2021-10-05 08:17:43 字數 2812 閱讀 2284

題目

問題描述

如果乙個序列的奇數項都比前一項大,偶數項都比前一項小,則稱為乙個擺動序列。即 a[2i]a[2i]。

小明想知道,長度為 m,每個數都是 1 到 n 之間的正整數的擺動序列一共有多少個。

輸入格式

輸入一行包含兩個整數 m,n。

輸出格式

輸出乙個整數,表示答案。答案可能很大,請輸出答案除以10000的餘數。

樣例輸入

3 4樣例輸出

樣例說明

以下是符合要求的擺動序列:

2 1 2

2 1 3

2 1 4

3 1 2

3 1 3

3 1 4

3 2 3

3 2 4

4 1 2

4 1 3

4 1 4

4 2 3

4 2 4

4 3 4

評測用例規模與約定

對於 20% 的評測用例,1 <= n, m <= 5;

對於 50% 的評測用例,1 <= n, m <= 10;

對於 80% 的評測用例,1 <= n, m <= 100;

對於所有評測用例,1 <= n, m <= 1000。

這道題我看網上很多大佬的解法都很巧妙,我這裡分享一下我對這道題的解法,這道題暴力求解肯定不能通過所有的結點。所以時要用到動態規劃的思想。

首先假設d[i][j]為第i列中以j結尾的方案總數。

此時有兩種情況。

1.當i是奇數時,這時如果以j結尾說明它前面一位數的值一定小於j所以方案數就為前面一行所有以小於j結尾的方案數。

即 d[i][j]=sum(d[i-1][1]+…+d[i-1][j-1]);

2.當i是偶數時,這時如果以j結尾說明它前面一位數的值一定大於j所以方案數就為前面一行所有以大於j結尾的方案數。

即 d[i][j]=sum(d[i-1][n]+…+d[i-1][j+1]);

此時我們很容易就寫出了動態規劃的基礎**

//動態規劃解 

#include

#include

#include

#include

#include

#include

#define maxn 1000005

#define pi 10000

using

namespace std;

int m,n;

int dp[

1005][

1005];

//記錄,表示第i列以j數字結尾的總數 時間複雜度o(n^3

intmain()

for(

int i=

2;i<=m;i++)}

}if(i%2==1

)}}}

long sum=0;

for(

int i=

1;i<=n;i++

) cout

}

可是此時的時間複雜都依然達到了o(n^3),顯然不能全部通過此題,

於是要進行**的優化,我們觀察奇數列d[i][j]=sum(d[i-1][1]+…+d[i-1][j-1]);

可知,等式右邊不就等於前面一列小於j結尾的方案數的和嘛,這就相當於1-(j-1)的字首和。

於是我們可以重新考慮狀態轉移方程

用dp1[i][j]表示第奇數列以從1 — j 的方案數的字首和;

用dp2[i][j]表示第偶數列以從1 — j 的方案數的字首和;

奇數列有如下的狀態轉移

dp1[i][j]=dp2[i-1][j-1]+dp1[i][j-1];

解釋:dp1[i][j]分為兩個部分,乙個就是1—(j-1)的字首和加上以j結尾的所有方案數,而以j結尾的方案數顯然等於前一列所有小於j-1的方案數即前一列1-(j-1)的字首和即dp2[i-1][j-1]。

偶數列同樣分析有,

dp2[i][j]=dp1[i-1][n]-dp1[i-1][j]+dp2[i][j-1];

即可的**

#include

#include

#include

#include

#include

#include

#define maxn 1005

#define pi 10000

using

namespace std;

typedef

long

long ll;

int n,m;

ll dp1[maxn]

[maxn]

;//儲存的是奇數列字首和

ll dp2[maxn]

[maxn]

;//儲存的是偶數列的字首和;

intmain()

if(dp2[i][1

]>pi)

for(

int j=

1;j<=n;j++

) dp2[i]

[j]%

=pi;

}else

if(dp1[i][2

]>pi)

for(

int j=

2;j<=n;j++

) dp1[i]

[j]%

=pi;}}

if(m%2)

cout<[n]%pi

cout<[n]%pi

}

藍橋杯模擬賽 擺動序列 題目 題解

題目 問題描述 如果乙個序列的奇數項都比前一項大,偶數項都比前一項小,則稱為乙個擺動序列。即 a 2i a 2i 小明想知道,長度為 m,每個數都是 1 到 n 之間的正整數的擺動序列一共有多少個。輸入格式 輸入一行包含兩個整數 m,n。輸出格式 輸出乙個整數,表示答案。答案可能很大,請輸出答案除以...

2019 藍橋杯省賽 B 組模擬賽(一)

d.結果填空 馬的管轄 e.填空 lis f.程式設計 找質數 思路 因為時間複雜度的問題,o n n 的時間複雜度可能會超時,可以選擇的篩選素數的方法有埃氏篩法o n logn 尤拉篩法,這裡選的是尤拉篩法o n 直接遍歷找兩個素數相加等於n 因為要求字典樹最小,所以不會超時 ac include...

2018 藍橋杯省賽 B 組模擬賽(一)

給你乙個序列,請你在其中求出一段最長嚴格上公升的部分,它不一定要連續。include includeusing namespace std int f 10000 b 10000 int lis int n res max res,f i return res 1 int main printf d...