zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Java 简单算法--打印乘法口诀(只使用一次循环)
    Java简单算法--求100以内素数
    ubuntu 16.04 chrome flash player 过期
    java 网络API访问 web 站点
    java scoket (UDP通信模型)简易聊天室
    leetcode1105 Filling Bookcase Shelves
    leetcode1140 Stone Game II
    leetcode1186 Maximum Subarray Sum with One Deletion
    leetcode31 Next Permutation
    leetcode834 Sum of Distances in Tree
  • 原文地址:https://www.cnblogs.com/Leohh/p/8469909.html
Copyright © 2011-2022 走看看