hdu4489 组合公式+dp

这里对于题意在说明一下, 题目中要求的排列必须是波浪形,每一个在排列中的人不是波峰就是波谷,如果它既不是波峰也不是波谷排列就是错的.

对于我这种数学渣渣来说,做一道dp题要好久,%>_<%   怎么想到的DP呢? 首先他看起来像搜素,但数据范围很大(对于深搜来说20就够大了),抱着试一试的心态用暴搜写了一下,结果在n=12是爆掉了,怎么优化慢了一倍的时间呢? 由于我剪枝能力一点都不高,然后我觉得搜素爆掉就要想dp,然后越想越觉得很对.

解题思路,假设n个人身高从1到n升序排列,我们先把题目分解成一个最小子问题,就是第n个人要插在哪里? 他前面有n-1人, 那么就有n个孔等着他插,假设他插到了第j个位置,前面有j-1人,后面有n-j人. 那么第一个式子就出来了,当第n个人在j位置时,对于这种情况的排列总数为前面j-1人的总排列数*后面n-j人的总排列数,这是不是就是很明显的dp了,求一个解必须已知其他的解,但现在其他的解没有规律无法求出,那么就找出规律来. 咱们在想,第n个人是不是一定最高,他插在j位置,他前面的那个人一定比他矮,那么第n个人前面的那个序列最后两人一定是降序排列的,我们设这种状态为0,那后面的那个序列的前面两人也一定是升序排列的,我们设为1,那么此时有dp[j][0]代表j个人最后两人是升序排列的总排列数,dp[n-j][1]代表n-j个人最前面两人是升序排列的.但是还没完,还有很重要的一点没有考虑到, 第n个人前面的j-1个人是不是不知道选谁,因为第n个人在最初排列中他前面有n-1个人这n-1中选哪几个站在第n个人前面呢? 不要考虑身高(因为对于波浪线来说总会有合适的)  这样是不是c(n-1,j-1)一下,前面的人确定了,后面的人也就随之确定了,所以就不用考虑了.

这样推到之后,有递推公式 c(n-1,j-1)*dp[j-1][0]*dp[n-j][1]  由于对称性 sum[n](n的总排列数)/2=dp[n][0]=dp[n][1],想一想对不对?

那么最终n的总排列数就等于把所有孔算完相加的值,代码如下.

 1 #include<cstdio>
 2 #include<cstring>
 3
 4 using namespace std;
 5
 6 __int64 dp[21][2];
 7 __int64 answer[21];
 8
 9 __int64 C(int x,int y)  //   xÊǵ×Êý
10 {
11     __int64 mother=1,son=1;
12     for(int i=0;i<y;i++)
13     {
14         mother*=(y-i);
15         son*=(x-i);
16     }
17     return son/mother;
18 }
19 int main()
20 {
21     for(int i=0;i<=20;i++){
22         for(int j=0;j<2;j++)
23             dp[i][j]=1;
24     }
25     answer[1]=1;
26     for(int i=2;i<=20;i++){
27         for(int j=1;j<=i;j++){
28             answer[i]+=C(i-1,j-1)*dp[j-1][0]*dp[i-j][1];
29
30         }
31         dp[i][0]=dp[i][1]=answer[i]/2;
32     }
33     int t;
34     scanf("%d",&t);
35     while(t--)
36     {
37         int k,n;
38         scanf("%d%d",&k,&n);
39         printf("%d ",k);
40         printf("%I64d\n",answer[n]);
41     }
42     return 0;
43 }

时间: 2024-12-30 03:27:18

hdu4489 组合公式+dp的相关文章

hdu 1799 (循环多少次?)(排列组合公式)

循环多少次? Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 3051    Accepted Submission(s): 1117 Problem Description 我们知道,在编程中,我们时常需要考虑到时间复杂度,特别是对于循环的部分.例如, 如果代码中出现 for(i=1;i<=n;i++) OP ; 那么做了n次OP运算

bzoj1227 [SDOI2009]虔诚的墓主人(组合公式+离散化+线段树)

1227: [SDOI2009]虔诚的墓主人 Time Limit: 5 Sec  Memory Limit: 259 MBSubmit: 803  Solved: 372[Submit][Status][Discuss] Description 小W 是一片新造公墓的管理人.公墓可以看成一块N×M 的矩形,矩形的每个格点,要么种着一棵常青树,要么是一块还没有归属的墓地.当地的居民都是非常虔诚的基督徒,他们愿意提前为自己找一块合适墓地.为了体现自己对主的真诚,他们希望自己的墓地拥有着较高的虔诚度

hdu4927 Series 1(组合+公式 Java大数高精度运算)

题目链接: Series 1 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Total Submission(s): 423    Accepted Submission(s): 146 Problem Description Let A be an integral series {A1, A2, . . . , An}. The zero-order series o

HDU 4869 Turn the pokers(思维+组合公式+快速幂)

Turn the pokers 大意:给出n次操作,给出m个扑克,然后给出n个操作的个数a[i],每个a[i]代表可以翻的扑克的个数,求最后可能出现的扑克的组合情况. Hint Sample Input: 3 3 3 2 3 For the this example: 0 express face down,1 express face up Initial state 000 The first result:000->111->001->110 The second result:0

排列组合公式

今天在写一个算法的时候用到了排列组合,突然感觉不熟悉了,于是自己搜索了下, 重新复习下,把笔记记下来,便于以后复习. 第一,排列 1)排列的定义,就是指从给定n个数的元素中取出指定r个数的元素,进行排序 2)排列公式 3 公式解读, 总长度为r,第一个人有n-0种选,第二个有n-1种,,,,最后一个有n-(r-1)种(为什么是减去(r-1) 因为到第r个人的时候,发现自己前面有r-1个人已经消耗了r-1个选择了,自己的选择余地变成n-(r-1),这和第一个人发现前面有0个选择已经消耗是一样道理)

杭电 2200 Eddy&#39;s AC难题 (排列组合 公式)用double来表示64位

Eddy's AC难题 Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3710    Accepted Submission(s): 1741 Problem Description Eddy是个ACMer,他不仅喜欢做ACM题,而且对于Ranklist中每个人的ac数量也有一定的研究,他在无聊时经常在纸上把Ranklist上每个人的

简明易懂的理解排列组合公式

说实话,我可能无意识中总是感觉自己数学不好,有时自己稍微陌生的数学内容就尽量的逃避,这哪能行,必须要去面对的.我又不是搞数学的研究,咱只是去应用就行了. 下面是知乎降解排列组合公式比较透彻的一个帖子 https://www.zhihu.com/question/26094736

hdu1261(高精度+组合公式的应用)

题目意思: 给定若干字母和它们相应的个数,计算可以组成多少个不同的字符 http://acm.hdu.edu.cn/showproblem.php?pid=1261 题目分析: 组合公式的直接应用,s!/(ai!) s:字符总数 ai:第i个字符的个数,用数组实现高精度的组合公式 不要直接求是S!的阶乘,那样会超时,需要上下同时求,约去最大公约数,在将剩下的值模拟相乘 AC代码: /** *s!/(ai!) s:字符总数 ai:第i个字符的个数 *(高精度) */ #include<iostre

hdu 4927 Series 1(组合+公式)

题目链接:hdu 4927 Series 1 题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 解题思路:n最多才3000,ai最大也才1000,貌似不会超int,但是要注意,有些数不止被计算了一次,最多的数被计算了C(15003000),所以肯定要用高精度处理,那么用o(n2)的复杂度肯定就跪了.其实对于最后的ans,ans=∑i=0n?1C(in?1)?ai?(?1)i+1(类似杨辉三角) import