UVA - 12034 Race (递推+dp)

题目大意:

    有一群马进行赛跑,可以有名次并列的情况存在,比如:如果是两匹马A、B,存在三种可能:A第一B第二、A第二B第一、AB并列。现在给你马的数量,问有几种可能的名次存在。

链接:题目在这里

题目思路:

  这个用递推还是比较明显的,现在我们知道两匹马的结果是3,那么如果多了一匹马呢?这匹马将会给结果带来什么改变?可以知道:当第三匹马过来时,他可能使得这群马产生了新的名次,也可能并不会(也就是说此时它与之前的两匹马中的一个并列);如果我们用f [ i ] [ j ]来表示i匹马跑出j个结果有多少种情况的话,

我们可以得到一个递推式子:f [ i ] [ j ] = ( f [ i - 1 ] [ j - 1 ] * j + f [ i - 1 ] [ j ] * j );(式子的推导可以画图后看出来),那么最后只要遍历一遍 j 就可以了;

另外需要注意的点就是题目中说 数据可能很大,要我们mod10056,在哪里%我第一次做的时候也错了很多次,后来知道一个公式:(a+b)%c=(a%c+b%c)%c

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#define maxn 1005
#define mod 10056

using namespace std;
int f[maxn][maxn];//i匹马创造了j个成绩的话有几种

int main(void)
{
     int t,n;
     long long sum;
     scanf("%d",&t);
     memset(f,0,sizeof(f));
     f[1][1]=1;f[2][1]=1;
     f[2][2]=2;
     for(int i=3;i<=1000;i++)//实现进行递推出结果
     {
          for(int j=1;j<=i;j++)
          {
               f[i][j]=(f[i-1][j-1]*j+f[i-1][j]*j)%mod;
          }
     }
     for(int i=1;i<=t;i++)
     {
          scanf("%d",&n);
          sum=0;
          for(int i=1;i<=n;i++)//要得到n匹马的结果,把它能跑出的每一种可能相加
          {
               sum=sum+f[n][i];
          }
          sum=sum%mod;//最后需要再%一次
          printf("Case %d: %lld\n",i,sum);
     }
     return 0;
}

呼呼

猜你喜欢

转载自blog.csdn.net/destiny1507/article/details/81412127