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

时间: 2024-10-11 22:02:14

Codeforces 869C The Intriguing Obsession:组合数 or dp的相关文章

codeforces 161D - Distance in Tree(树形dp)

题目大意: 求出树上距离为k的点对有多少个. 思路分析: dp[i][j] 表示 i 的子树中和 i 的距离为 j 的点数有多少个.注意dp[i] [0] 永远是1的. 然后在处理完一颗子树后,就把自身的dp 更新. 更新之前更新答案. 如果这颗子树到 i 有 x 个距离为j的.那么答案就要加上 dp[i] [ k-j-1] * x; #include <iostream> #include <cstdio> #include <cstring> #include &l

CodeForces 258B Little Elephant and Elections 数位DP

前面先用数位DP预处理,然后暴力计算组合方式即可. #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <climits> #include <string> #include <iostream> #include <map> #include <cstdlib> #include

Codeforces 437E The Child and Polygon(区间DP)

题目链接:Codeforces 437E The Child and Polygon 题目大意:给出一个多边形,问说有多少种分割方法,将多边形分割为多个三角形. 解题思路:首先要理解向量叉积的性质,一开始将给出的点转换成顺时针,然后用区间dp计算.dp[i][j]表示从点i到点j可以有dp[i][j]种切割方法.然后点i和点j是否可以做为切割线,要经过判断,即在i和j中选择的话点k的话,点k要在i,j的逆时针方. #include <cstdio> #include <cstring&g

Codeforces 219D. Choosing Capital for Treeland (树dp)

题目链接:http://codeforces.com/contest/219/problem/D 树dp 1 //#pragma comment(linker, "/STACK:102400000, 102400000") 2 #include <algorithm> 3 #include <iostream> 4 #include <cstdlib> 5 #include <cstring> 6 #include <cstdio&

CodeForces Round#229 DIV2 C 递推DP

对这道题目也只好说呵呵了,没注意k的范围最大才10,所以昨晚纠结了很久,没什么好的方法来处理,后来无奈想去翻翻题解,发现人家开头就来了句,因为k的范围比较小 所以.........我只好暂停马上回头看看题目,是的,k比较小所以完全可以先在询问前预处理DP一遍, DP就比较清晰了,dp[i][j]  (i>=0 && i<k,,,,j>=i && j <=n)代表意义呢 以i为开头的  区间[1,j]注意 是 1~j的 所需要的操作数,题目问的是最小操

codeforces 235B Let&#39;s Play Osu! 概率dp

题意:给定n表示有n个格子,下面每个格子为O的概率是多少.对于一段连续 x 个O的价值就是 x^2 ;求获得的价值的期望是多少. 思路:n^2=n×(n-1)+n,设ai为第i段连续O的长度,∑ai^2 = ∑[ ai+ ai*(ai-1) ] = ∑ ai*(ai-1) + ∑ai = ∑ C(ai, 2)*2 + ∑ai,那么问题可以转 化为求长度大于1的连续段数*2+O的个数的总期望. ∑ai我们可以理解为O的总个数,所以它的期望为∑pi: C(ai, 2)*2我们可以认 为是连续ai个O

Codeforces 235B Let&#39;s Play Osu! (概率dp求期望+公式变形)

B. Let's Play Osu! time limit per test:2 seconds memory limit per test:256 megabytes You're playing a game called Osu! Here's a simplified version of it. There are n clicks in a game. For each click there are two outcomes: correct or bad. Let us deno

Codeforces 235B Let&#39;s Play Osu! 概率dp(水

题目链接:点击打开链接 给定n表示有n个格子 下面每个格子为O的概率是多少. 对于一段连续 x 个O的价值就是 x*x ; 问: 获得的价值的期望是多少. 思路: 把公式拆一下.. #include <cstdio> const int N = 100005; double dp[N][2], p[N]; int main(){ int n; scanf("%d", &n); for(int i = 1; i <= n; i ++) { scanf("

C - The Intriguing Obsession /* Codeforces Round #439 */ (dp )

- This is not playing but duty as allies of justice, Nii-chan! - Not allies but justice itself, Onii-chan! With hands joined, go everywhere at a speed faster than our thoughts! This time, the Fire Sisters - Karen and Tsukihi - is heading for somewher