UVALive 6176 Faulhaber's Triangle

题目链接 http://acm.sdibt.edu.cn/vjudge/ojFiles/uvalive/pdf/61/6177.pdf

题意是  给定一个数n,代表着一共有n个人,且他们的身高从1到n。 要求让这n个人站成一行,使得身高的排列呈波浪形,比如低高低或者高低高。

 

注意:n = 1 ,  ans = 1;

      n = 2 ,  ans = 2;

 

动态规划。

 

解题思路: 每次新加入的点k,可以看成将之前的序列分成前后两部分,并且因为 k是最大的,所以要求k前面数的趋势应该是高低,k后面的趋势应该是底高。这样加入k后的排列数,就是前后可行排列方法数的

乘积。 枚举k插入的位置i,以及乘上c[k][i],表示从k个数里面取i个数的取法。

那么怎么计算前后可行排列的方法数呢? 经过推导后,可以证明,前面和后面的方法数是相同的,所以假设用dp[n][0]表示前n个数中以高低为结尾的方法数,dp[n][1]表示前n个数中以底高为开始的方法数,ans[n]表示n个人的时候的方法数,可得 dp[n][0] = dp[n][1] = ans[n] / 2;

 

代码:

 1 #include<cstdio>
 2 #include<cstdlib>
 3 #include<cstring>
 4 #include<string.h>
 5 #include<cmath>
 6 #include<algorithm>
 7 #include<queue>
 8 #include<stack>
 9 #include<deque>
10 #include<map>
11 #include<iostream>
12 using namespace std;
13 typedef long long  LL;
14 const double pi=acos(-1.0);
15 const double e=exp(1);
16 const int N = 100009;
17 
18 LL a[25];
19 LL c[25][25];
20 LL sta[25][3],ans[25];
21 
22 void init_c()
23 {
24     LL i,p,j;
25     LL x = 1;
26     for(i = 1; i <= 20; i++)
27     {
28         x *= i;
29         a[i] = x;
30     }
31     a[0] = 1;
32 
33     for(i = 1; i <= 20; i++)
34     {
35         for(j = 0; j <= i; j++)
36         {
37             c[i][j] = a[i] / a[j] / a[i - j];
38         }
39     }
40 }
41 
42 
43 void init_tab()
44 {
45     LL i,p,j;
46 
47     sta[0][0] = sta[0][1] = 1;  //特判 k 插在第一位和最后一位的情况
48     ans[1] = 1;
49     sta[1][0] = sta[1][1] = 1;  //特判 n = 1时,既可以看成是开始为底高的方法数也可以看成是高低的方法数。  
50 
51     for(i = 2; i <= 20; i++)
52     {
53         for(j = 0; j <= i - 1; j++)
54         {
55             ans[i] += sta[j][0] * sta[i - j - 1][1] * c[i - 1][j];
56         }
57         sta[i][0] = sta[i][1] = ans[i] / 2;
58     }
59 }
60 
61 int main()
62 {
63     LL i,p,j,n,t;
64     LL w;
65 
66     init_c();
67     init_tab();
68 
69     scanf("%lld",&t);
70     while(t--)
71     {
72         scanf("%lld%lld",&w,&n);
73         printf("%lld %lld\n",w,ans[n]);
74 
75     }
76     return 0;
77 }
View Code

 

转载于:https://www.cnblogs.com/daybreaking/p/10625268.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值