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