2247. 迷恋(love)

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

输入
第一行也仅包含三个空格分隔的整数a,b和c(1≤a,b,c≤5 000),表示红色,蓝色和紫色怪物的岛数。

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

样例输入
样例输入1

1 1 1

样例输入2

1 2 2

样例输入3

1 3 5

样例输出
样例输出1

8

样例输出2

63

样例输出3

3264

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

数据范围限制
对于50%的数据,a,b,c都小于等于5。
对于100%的数据 a,b,c小于等于5000。

思路:
设f[i][j]表示两个群岛(A,B)各自有i和j个岛相连时,之间有多少种建路方案。

初始化:f[05000][0]=f[0][05000]=1.
根据题意,不相连也是一种方案。

动态转移方程: f [ i ] [ j ] = f [ i − 1 ] [ j ] + f [ i − 1 ] [ j − 1 ] ∗ j f[i][j]=f[i-1][j]+f[i-1][j-1]*j f[i][j]=f[i1][j]+f[i1][j1]j

对于f[i][j],可分两种情况。
有点类似背包思想。
对于新加入的第i号岛,它可以选择与B1,B2…Bj号岛相连或不相连。
不相连:
就是f[i-1][j],不懂去看背包吧。

相连:
根据乘法原理,就等于j*f[i-1][j-1]。我们先强制让Ai号岛与B的任意号岛相连,有j种方案。因为两边都少了一个岛,剩下的即f[i-1][j-1]。
在这里插入图片描述

最后的值就等于(乘法原理) f [ a ] [ b ] ∗ f [ b ] [ c ] ∗ f [ a ] [ c ] . f[a][b]*f[b][c]*f[a][c]. f[a][b]f[b][c]f[a][c].
记得每一步都需要做取余。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<string>
#include<algorithm>
#include<vector>
#define fre(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout);
using namespace std;
const int MAX=2147483647;
const int N=1e6;
const long long Mod=998244353;
long long f[5010][5010],a,b,c;
int main()
{
	//fre(love);
	scanf("%lld%lld%lld",&a,&b,&c);
	for(int i=0;i<=5000;i++) f[0][i]=f[i][0]=1;
	for(int i=1;i<=5000;i++)
	for(int j=1;j<=5000;j++)
		f[i][j]=(f[i-1][j]+j*f[i-1][j-1])%Mod;
	printf("%lld\n",(f[a][b]*f[b][c]%Mod)*f[a][c]%Mod);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值