• 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 }
  • 相关阅读:
    在线程中进行读取并写入文件和wenjia
    Java里的IO流里的FileInputStream 的读取并在前打印行数!
    C++基础知识(前言)
    linux shell 笔记
    AngularJS图片上传功能的实现
    jQuery中事件绑定
    项目实践中--Git服务器的搭建与使用指南
    javascript跨浏览器事件对象类库
    完美运动框架(js)
    浅谈js中继承的理解和实现
  • 原文地址:https://www.cnblogs.com/Leohh/p/8469909.html
Copyright © 2020-2023  润新知