牛客练习赛62 病毒扩散

牛客训练赛62 B题病毒扩散

链接:https://ac.nowcoder.com/acm/contest/5205/B
来源:牛客网

题目描述
牛牛所在的城市有一种新型病毒开始扩散。在一个二维平面坐标系上,有一个感染者在 (0,0) 的位置。从 时刻 0 开始,每一个在 (x,y) 的感染者都会让下一个时刻 (x+1,y),(x,y+1) 的感染者数量增加 1。
在这里插入图片描述
链接:https://ac.nowcoder.com/acm/contest/5205/B
来源:牛客网

上图展示了时刻 0 和时刻 1 病毒的扩散情况。在时刻 1,(0,0),(0,1),(1,0) 的感染者数量为 1。在时刻 2,(0,0),(0,2),(2,0) 的感染者数量为 1, (0,1),(1,0),(1,1) 的感染者数量为 2。

牛牛想知道,对于特殊的 n 个点,在时刻 t 感染者的数量。

输入描述:
第一行一个正整数n,表示特殊点的数量。

接下来 n 行,每行三个非负整数 xi,yi,ti,表示有一个特殊的点在 (xi,yi),牛牛想知道在时刻 ti,这个点有多少感染者。
输出描述:
对于每一个特殊的点,输出一行一个非负整数,表示在 t 时刻这个点的感染者数量,对 998244353 取模。

示例1
输入

3
0 0 1
1 1 2
2 0 2

输出
1
2
1

示例2
输入

5
5 5 7
2 7 9
0 14 14
0 14 15
14 29 100

输出

0
36
1
15
891148910

思路:首先画图分析前几秒内的每个格子的感染人数分布

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这里只列举到t=4的情况。
由列举出来的图表可以很轻易的发现规律
围城边界的数列是 (x+1)^t 的展开式的系数。
t=0时,各项系数为1
t=1时,各项系数为1,1
t=2时,各项系数为1,2,1
t=3时,各项系数为1,3,3,1
t=4时,各项系数为1,4,6,4,1
t=5时,各项系数为1,5,10,10,5,1
每一时间的非0部分所围成的三角形的边界都是由这个系数所组成的
除此之外,我们可以发现斜着的直线上的数列,也是跟这个系数成比例的
在这里插入图片描述
这些斜线的方程为 x+y=c(c为常数)
t=5
斜线上的数字:
x+y=0时,斜线上只有一个数字1
x+y=1时,斜线上的数字有5,5 与1,1成比例
x+y=2时,斜线上的数字有10,20,10 与1,2,1成比例

并且可以发现,比例为当前 t 所对应的这个系数

所以我们创建一个二维数组a[][]
a[i][j]表示,当t=i时,上述的系数的第j个数字
例如: a[5][3] 表示 t=5 时的系数表的第3个数字
t=5 时系数表为 1,5,10,10,5,1
下标从0开始,所以a[5][3]=10

将这么一个二维表建立后,剩下的就可以通过这个表中的数据O(1)的求出答案。

这个表也很容易找到规律
在这里插入图片描述
a [ i ] [ j ] = a [ i-1 ] [ j ] + a [ i-1 ] [ j-1 ];

然后可以通过判断
给出的点是否位于边界,分类的计算答案

当给出的点不在边界时,
ans = a [ x+y ] [ x ] * a [ t ] [ x+y ]

例如 x=2,y=1,t=5 时
在这里插入图片描述
2,1)这个点位于x+y=3上他的值应该是t=3时的系数(1,3,3,1)中的第2(x)(其实这里选x和y都一样=。=!)个乘上10(t=5时的第(2+1)(x+y)个系数)
由此总结出公式:
ans = a [ x+y ] [ x ] * a [ t ] [ x+y ];

ac代码如下

#include<bits/stdc++.h>
using namespace std;
const int mod=998244353;
long long a[5005][5005];
int main(){
	
	a[0][0]=1;
	for (int i=1;i<=5000;i++){//建表
		for (int j=i;j>=0;j--){
			a[i][j]=(a[i-1][j-1]+a[i-1][j])%mod;
		}
	}
	int n,x,y,t;
	scanf("%d",&n);
	while(n--){
		scanf("%d %d %d",&x,&y,&t);
		if ((x+y)>t){//当给出的点在目前已经建成的三角形外时
			printf("0\n");
			continue;
		}
		if (x==0){//处于边界
			printf("%d\n",a[t][y]);
		}
		else if (y==0){//处于边界
			printf("%d\n",a[t][x]);
		}
		else if (x+y==t){//处于边界
			printf("%d\n",a[t][x]);
		}
		else {//位于三角形内部
			printf("%d\n",(a[x+y][x]*a[t][x+y])%mod);//
		}
	}
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值