Codeforces 869C The Intriguing Obsession:組合數 or dp

Leohh發表於2018-02-25

題目連結: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 }

 

相關文章