シーケンスの奇数アイテムがすべて前のアイテムより大きく、偶数アイテムがすべて前のアイテムよりも小さい場合、ウォブルシーケンスと呼ばれます。つまり、a [2i] <a [2i-1]、a [2i + 1]> a [2i]です。
Xiao Mingは、長さがmで、各数値が1からnまでの正の整数であるスイングシーケンスの数を知りたいと考えています。
入力フォーマット
入力行には2つの整数mとnが含まれています。
出力フォーマット
答えを示す整数を出力します。答えが非常に大きくなる可能性があります。答えを10000で割った余りを出力してください。
入力例
3 4
出力例
14
サンプル概要
以下は、要件を満たすスイングシーケンスです。21
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。
質問の意味:1からnの範囲で長さmのスイングシーケンスの数を見つける
アイデア:対象のデータ量によると、ブルートフォース検索は絶対に合格しません。この種のスイングは自然にDPに関連付けられますが、問題はこの変化をどのように表現するかです。ここでは、dp [i] [j]を使用して次のことを表現できます。
奇数:i番目の桁が最小の数jの場合、いくつ:
偶数:i桁目がjの最大数の場合:
iが偶数の場合:dp [i] [j] = dp [i-1] [j + 1] + dp [i] [j-1];(ここで、i番目の数字が表されると、最大数がjの場合、i桁目の最大数がj-1の場合と、i-1桁目の最小数がj + 1の場合(i桁目がjの場合)の2つに分かれます)
iが奇数の場合:dp [i] [j] =(dp [i-1] [j-1] + dp [i] [j + 1]);(ここでは、i番目の数字を表すものとして理解できます。最小数がjの場合、i桁目の最小数がj + 1の場合と、i-1桁目の最大数がj-1の場合(つまり、i桁目がjの場合)の2つに分かれます。
最後に、全長が奇数の場合はdp [m] [1]、偶数の場合はdp [m] [n]になります。
コード:
#include <iostream>
using namespace std;
int dp[1010][1010];
int main() {
// m为长度,n为数的范围
int m,n;
cin>>m>>n;
for(int i = 1; i <= n; i++)
dp[1][i] = n - i + 1;
for(int i = 2; i <= m; i++)
if(i & 1)
for(int j = n; j >= 1; j--)
dp[i][j] = (dp[i-1][j-1] + dp[i][j+1]) % 10000;
else
for(int j = 1; j <= n; j++)
dp[i][j] = (dp[i-1][j+1] + dp[i][j-1]) % 10000;
int ans = m & 1 ? dp[m][1] : dp[m][n];
cout<<ans;
return 0;
}