牛牛所在的城市有一种新型病毒开始扩散。在一个二维平面坐标系上,有一个感染者在 (0,0) 的位置。从 时刻 0 开始,每一个在(x,y) 的感染者都会让下一个时刻 (x+1,y),(x,y+1) 的感染者数量增加 1。
今天晚上又是一场自闭赛,一道题目都没有做出来,真的好丢人。。
我真的很厌恶那些天才,真的是,直接一句话,直觉,就完事了?思路如何想?啥都没有。我要严密的逻辑!!
麻蛋想想我就气!
直接上暴力 f [ k ] [ i ] [ j ] = f [ k − 1 ] [ i ] [ j ] + f [ k − 1 ] [ i − 1 ] [ j ] + f [ k − 1 ] [ i ] [ j − 1 ] f[k][i][j] = f[k - 1][i][j] + f[k-1][i-1][j] + f[k - 1][i][j- 1] f[k][i][j]=f[k−1][i][j]+f[k−1][i−1][j]+f[k−1][i][j−1]
观察这个状态转移可能是什么问题,emmmm。一开始我列出来这个表达式,也想转一下问题,但是奈何做题太少,真的是欲哭无泪,但是做完题目,看了下他们的AC代码,想了一会,大概明白了是怎么回事了。
要想转化成某个问题,首先要将每个维度所表示的状态确定好,这个状态转移方程其实表示,第一维表示时间,二三维表示的是点,那么这就转化成了方案数的问题了。
在每一个时间单位,有三种选择:
- ( x , y ) (x,y) (x,y)
- ( x − 1 , y ) (x-1, y) (x−1,y)
- ( x , y − 1 ) (x, y -1) (x,y−1)
我们只要明白了转化的过程,就差不多能做出来了,就是一个组合问题!
#include <iostream>
#include <cstring>
using namespace std;
const int N = 5010, mod = 998244353;
typedef long long LL;
LL f[N], unf[N];
int qmi(int a, int b)
{
int res = 1;
while (b)
{
if (b & 1) res = (LL) res * a % mod;
b >>= 1;
a = (LL) a * a % mod;
}
return res;
}
int main()
{
f[0] = 1;
for (int i = 1; i <= 5000; i ++) f[i] = (LL) f[i - 1] * i % mod;
unf[0] = 1;
for (int i = 1; i <= 5000; i ++) unf[i] = (LL) unf[i - 1] * qmi(i, mod - 2) % mod;//求逆元
int T; scanf("%d", &T);
while (T --)
{
int x, y, t; scanf("%d %d %d", &x, &y, &t);
if (t < x + y)
{
printf("0\n");
continue;
}
LL ans = (LL)f[t] * unf[x] % mod * unf[y] % mod * unf[t - x - y] % mod;
printf("%lld\n", ans);
}
return 0;
}