题意是求1-n 的全排列中有多少呈现高低高低高低或者地高低高形式排列的个数。
这种排列叫做:alternating permutations 或者 Extremal Permutations 。
可以用DP做。
dp(n,k)表示:长度为n,最后一个数为k,最后两个数是递增的? 排列的个数;
dp2(n,k)表示:长度为n,最后一个数为k,最后两个数是递减的 排列的个数;
那么:
dp(n,k) = dp2(n,n+1-k) ;
很好理解吧,比如说132(低高低)等价于312(高低高),相对的位置加起来等于4.
那么我们针对dp[n][k]的最后一位进行如下考虑:
最后一位是k,因为dp[n][k]最后两个数字是递增的,所以第n-1位的最大值是k-1。那么我们很容易推导出DP方程:
?
?
又:
?

所以:dp(n,k) = dp(n-1,n+1-k) + dp(n,k-1);
边界条件略。
代码:
[cpp]
#include ??
#include ??
#include ??
#include ??
using namespace std;?
?
#define Maxn 25??
#define LL long long??
LL dp[Maxn][Maxn];?
LL ans[Maxn];?
?
?
void init()?
{?
??? memset(dp,0,sizeof(dp));?
??? memset(ans,0,sizeof(ans));?
??? dp[1][1] = 1;?
??? ans[1] = 1;?
??? for(int i=2;i<=20;i++)?
??? {?
??????? for(int k=2;k<=i;k++)?
??????? {?
??????????? dp[i][k] = dp[i-1][i+1-k] + dp[i][k-1];?
??????????? ans[i] += dp[i][k];?
??????? }?
??????? ans[i] *=2;?
??????? //printf("%lld\n",ans[i]);??
??? }?
}?
int main()?
{?
#ifndef ONLINE_JUDGE??
??? freopen("in.txt","r",stdin);?
#endif??
??? init();?
??? int p;?
??? int m,n;?
??? scanf(" %d",&p);?
??? while(p--)?
??? {?
??????? scanf(" %d %d",&m,&n);?
??????? printf("%d %lld\n",m,ans[n]);?
??? }?
??? return 0;?
}?