[DP]迷恋

题面

题目描述

- 这不是正义的义务,而是作为正义的盟友!
- 不是盟友,而是正义本身, O n i i − c h a n Onii-chan Oniichan
这一次,火姐妹 - 凯伦和 T s u k i h i Tsukihi Tsukihi - 正在前往他们从未到达的地方 - 水包围的岛屿!
有三种群岛,分别有三种颜色红色,蓝色和紫色的怪物。每种颜色的岛屿分别有 a a a, b b b, c c c个。
桥梁在一些(可能全部或者部分)岛屿之间建成。桥梁双向连接两个不同的岛屿并具有长度 1 1 1.对于任何两个相同颜色的岛屿,他们彼此不可达,或者它们之间的最短距离至少为 3 3 3。这是为了防止同一种颜色的怪物种群相互蔓延。
火姐妹已经准备好了,但他们也想测试你的勇气。你在这里找出在限制下建立所有桥梁的不同方式的数量,并给出答案模数 998244353 998244353 998244353(即答案要取余数)。只要有一对建桥的岛屿不一样,那么两种方法就是不一样的。

输入

第一行也仅包含三个空格分隔的整数 a a a b b b c c c ( 1 ≤ a , b , c ≤ 5000 ) (1\le a,b,c\le 5 000) 1abc5000 - 红色,蓝色和紫色怪物的岛数。

输出

输出一行包含整数 - 构建桥接的不同方式的数量,模数为 998244353 998244353 998244353

样例

输入1

1 1 1

输出1

8

输入2

1 2 2

输出2

63

输入3

1 3 5

输出3

3264

提示

在第一个例子中,有 3 3 3个桥可以建立,没有桥梁的设置违反了限制。所以答案是 2 3 = 8 2^3 = 8 23=8
在第二个例子中,下图中的上两个结构是有效的,下两个是无效的。

数据范围
对于 50 % 50\% 50%的数据, a , b , c ≤ 5 a,b,c \le 5 a,b,c5
对于 100 % 100\% 100%的数据 a , b , c ≤ 5000 a,b,c \le5000 a,b,c5000

解析

考试怎么都没想到DP
本来以为 a , b , c ≤ 5 a,b,c\le 5 a,b,c5可以打表,
没想到 a = b = c = 5 a=b=c=5 a=b=c=5
答案为 3695119336 ≡ 700386277 m o d    998244353 3695119336\equiv700386277 \mod 998244353 3695119336700386277mod998244353
根本不可能
其实可以发现

规律1:

同一个点不可以和两个同样颜色的点相连就像下图
在这里插入图片描述
显然是错误的

规律2

对于一个岛,它连接两个不同颜色的岛之间的连线是不受影响的,
例如在这里插入图片描述
这三条线段是互不干扰的

推论1

根据 结论2 答案可以统计为:
( { x , y } \{x,y\} {x,y}表示为两种颜色的岛(一种x个,一种y个)之间的方案数)
{ a , b } × { b , c } × { a , c } \{a,b\}\times\{b,c\}\times\{a,c\} {a,b}×{b,c}×{a,c}(乘法原理)

DP

所以设 f i , j f_{i,j} fi,j表示两种颜色的岛(一种x个,一种y个)之间的方案数
则:
f i , j = j × ( f i − 1 , j − 1 ) + f i − 1 , j { 1 ≤ i , j ≤ max ⁡ { a , b , c } } f_{i,j}=j\times\left(f_{i-1,j-1}\right)+f_{i-1,j} \{1\le i,j\le \max\left\{a,b,c\right\}\} fi,j=j×(fi1,j1)+fi1,j{1i,jmax{a,b,c}}
其中 j × f i − 1 , j − 1 j\times f_{i-1,j-1} j×fi1,j1表示 i i i岛选出 1 1 1个连到 j j j岛有 j j j种选择后, i , j i,j i,j都有一个岛不能再连其他岛
(规律1)

代码

#include<bits/stdc++.h>
#define M 998244353
using namespace std;
long long a,b,c,m,f[5039][5039];
int main(){
	scanf("%lld%lld%lld",&a,&b,&c);m=(a>b&&a>c)?a:(b>c)?b:c;
	register int i,j;
	for(i=0;i<=m;i++){f[0][i]=f[i][0]=1;}
	for(i=1;i<=m;i++){for(j=1;j<=m;j++){f[i][j]=(j*f[i-1][j-1]%M+f[i-1][j]%M)%M;}}
	printf("%lld",((f[a][b]%M*f[b][c]%M)%M*f[a][c]%M)%M);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值