Codeforces 869C The Intriguing Obsession:组合数 or dp

题目链接:http://codeforces.com/problemset/problem/869/C

题意:

  红色、蓝色、紫色的小岛分别有a,b,c个。

  你可以在两个不同的岛之间架桥,桥的长度为1。

  任意两个颜色相同的岛之间的距离不能小于3。

  问你合法的架桥方案数。

题解:

  显然只能在不同颜色的岛之间连边。

  而且一个岛对于一种颜色,最多只能连一个岛。

  设f(x,y)表示两种颜色的岛相互连边,分别有x,y个,连边的方案数。(x < y)

  那么ans = f(a,b) * f(b,c) * f(a,c)

  解法1(组合数):

    枚举共连了k条边,k∈[1,x]。

    那么连了k条边的方案数 = C(x,k) * C(y,k) * k!

    总方案数f(x,y) = ∑(C(x,k) * C(y,k) * k!)

  解法2(dp):

    向其中A集合中加入一个岛,要么不连边,要么根B集合中的任意一个点连边(共j种方案)。

    f(i,j) = f(i-1,j) + f(i-1,j-1)*j

AC Code(combination):

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 5005
 5 #define MOD 998244353
 6 
 7 using namespace std;
 8 
 9 int mx=0;
10 int a[3];
11 long long f[MAX_N];
12 long long c[MAX_N][MAX_N];
13 long long ans=1;
14 
15 void cal_f()
16 {
17     f[0]=1;
18     for(int i=1;i<=mx;i++) f[i]=f[i-1]*i%MOD;
19 }
20 
21 void cal_c()
22 {
23     c[0][0]=1;
24     for(int i=1;i<=mx;i++)
25     {
26         c[i][0]=1;
27         for(int j=1;j<=i;j++)
28         {
29             c[i][j]=(c[i-1][j-1]+c[i-1][j])%MOD;
30         }
31     }
32 }
33 
34 int main()
35 {
36     for(int i=0;i<3;i++)
37     {
38         cin>>a[i];
39         mx=max(mx,a[i]);
40     }
41     cal_f();
42     cal_c();
43     for(int i=0;i<3;i++)
44     {
45         for(int j=i+1;j<3;j++)
46         {
47             int x=min(a[i],a[j]);
48             int y=max(a[i],a[j]);
49             int sum=0;
50             for(int k=0;k<=x;k++)
51             {
52                 sum=(sum+c[x][k]*c[y][k]%MOD*f[k])%MOD;
53             }
54             ans=ans*sum%MOD;
55         }
56     }
57     cout<<ans<<endl;
58 }

AC Code(dp):

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #define MAX_N 5005
 5 #define MOD 998244353
 6 
 7 using namespace std;
 8 
 9 int a,b,c;
10 long long dp[MAX_N][MAX_N];
11 
12 int main()
13 {
14     cin>>a>>b>>c;
15     int mx=max(a,max(b,c));
16     for(int i=0;i<=mx;i++)
17     {
18         dp[i][0]=dp[0][i]=1;
19     }
20     for(int i=1;i<=mx;i++)
21     {
22         for(int j=1;j<=mx;j++)
23         {
24             dp[i][j]=(dp[i-1][j]+dp[i-1][j-1]*j)%MOD;
25         }
26     }
27     cout<<dp[a][b]*dp[b][c]%MOD*dp[a][c]%MOD<<endl;
28 }
原文地址:https://www.cnblogs.com/Leohh/p/8469909.html