题面
题目描述
- 这不是正义的义务,而是作为正义的盟友!
- 不是盟友,而是正义本身,
O
n
i
i
−
c
h
a
n
Onii-chan
Onii−chan!
这一次,火姐妹 - 凯伦和
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) (1≤a,b,c≤5000) - 红色,蓝色和紫色怪物的岛数。
输出
输出一行包含整数 - 构建桥接的不同方式的数量,模数为 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,c≤5。
对于
100
%
100\%
100%的数据
a
,
b
,
c
≤
5000
a,b,c \le5000
a,b,c≤5000
解析
考试怎么都没想到DP
本来以为
a
,
b
,
c
≤
5
a,b,c\le 5
a,b,c≤5可以打表,
没想到
a
=
b
=
c
=
5
a=b=c=5
a=b=c=5时
答案为
3695119336
≡
700386277
m
o
d
998244353
3695119336\equiv700386277 \mod 998244353
3695119336≡700386277mod998244353
根本不可能
其实可以发现
规律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×(fi−1,j−1)+fi−1,j{1≤i,j≤max{a,b,c}}
其中
j
×
f
i
−
1
,
j
−
1
j\times f_{i-1,j-1}
j×fi−1,j−1表示
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);
}