问的是n个不一样的数,大小交替,或者小大交替的种类数量。
n个数,想象成[1,n]的自然数即可。
我们假设大小交替得到的长度为i的排列数为dp1[i],小大交替得到的长度为i的排列数为dp2[i],因为是对称的,其实应该有dp1=dp2,我们要计算的总和sum=dp1+dp2。
我们从小到大考虑各个数,一个个插入队列,考虑到第i个数,称为ai,ai比前i-1个数都大,可以插入的位置j∈[1,i]。
ai插入的位置为j时,前面的i-1个人比自己小,选择出来排列的情况有C(i-1,j-1)。插入第j个位置,ai属于“高”,要求ai前面和ai衔接的情况是低高,ai和后面一个衔接的情况是低高。所以插入j位置时候的排列数有 dp1[j-1] * dp2[i - j] * c[i-1][j-1]种。
#include <bits/stdc++.h> using namespace std; #define ll long long #define mst(a,b) memset(a,b,sizeof(a)) #define rep(i,a,b) for(ll i=(a);i<(b);++i) const int inf = 0x3f3f3f3f, maxN = 25 + 5; int N, M, T; ll dp1[maxN]; ll dp2[maxN]; ll sum[maxN]; ll c[maxN][maxN]; ll cal(int n, int m) { c[1][0] = c[1][1] = 1; rep(i, 2, n) { c[i][0] = 1; rep(j, 1, n) c[i][j] = c[i - 1][j] + c[i - 1][j - 1]; } } int main() { #ifndef ONLINE_JUDGE freopen("data.in", "r", stdin); #endif cal(20, 20); dp1[0] = dp1[1] = dp2[0] = dp2[1] = 1; sum[1] = 1; rep(i, 2, 20 + 1) { sum[i] = 0; rep(j, 1, i + 1) sum[i] += (dp1[j - 1] * dp2[i - j] * c[i - 1][j - 1]); dp1[i] = dp2[i] = sum[i] / 2; } scanf("%d", &T); rep(i, 1, T + 1) { scanf("%d%d", &M, &N); printf("%d %lld\n", M, sum[N]); } return 0; }
HDU 4489 The King's Ups and Downs
原文地址:https://www.cnblogs.com/Rosebud/p/9077030.html
时间: 2024-10-11 21:00:46