Hrbust 2143 积分大小【dp】

来源:互联网 发布:karunesh 知乎 编辑:程序博客网 时间:2024/06/05 18:55

积分大小Time Limit: 1000 MSMemory Limit: 32768 KTotal Submit: 25(21 users)Total Accepted: 17(16 users)Rating: Special Judge: NoDescription

暑期集训开始了,集训队里有N个人,每个人有一定的积分值,每个人等积分可能相等也可能不等,那一共有多少种积分大小的可能呢?

例如,N==2,那么有可能第一个人比第二个人积分高,有可能俩人积分相等,有可能第二个人比第一个人积分高,一共三种可能。

Input

每组数据第一行1个整数N,代表有N个人(1N<19

Output

对于每组数据输出一个整数占一行,代表N人之间的积分大小有多少种可能。

Sample Input

2

3

Sample Output

3

13

Hint

n == 3 假设三人积分分别是abc,那么有如下关系

a=b=c,a>b=c,a>b>c,a>c>b,a=b>c,a=c>b,b>a>c,b>c>a,b=c>a,b>a=c,c>a>b,c>b>a,c>b=a,共13种。Source2014暑假集训练习赛(8月6日)

思路:


1、考虑dp,设定dp【i】【j】.表示此时一共有i个人,并且总共有j个积分大小的情况的时候有多少种情况。


2、那么不难推出其状态转移方程:

①dp【i】【j】+=dp【i-1】【j】*j;表示我们当前加入的第i个人是和(i-1)个人中的某一种积分大小相同的状态转移。

②dp【i】【j】+=dp【i-1】【j-1】*j;表示我们当前加入的第i个人是和(i-1)个人中的所有积分大小都不同的情况,那么对应我们有j种选择:

比最高分的人分数还高,比第二高的高但是比最高的低,比第三高的高但是比第二高的低..................比最小的高,但是比次小的低,比最小的还低(一共j种情况);


3、那么ans【i】=Σdp【i】【j】(1<=j<=i)


Ac代码:

#include<stdio.h>#include<string.h>using namespace std;#define ll long long intll dp[25][25];ll ans[25];void init_Dp(){    memset(dp,0,sizeof(dp));    for(int i=1;i<19;i++)    {        for(int j=1;j<19;j++)        {            if(j==1)            {                dp[i][j]=1;            }            else            {                dp[i][j]=dp[i-1][j]*j+dp[i-1][j-1]*j;            }        }    }    for(int i=1;i<19;i++)    {        for(int j=1;j<=i;j++)        {            ans[i]+=dp[i][j];        }    }}int main(){    init_Dp();    int n;    while(~scanf("%d",&n))    {        printf("%lld\n",ans[n]);    }}





0 0