【题解】SP19149 Virus Revisited

版权声明:Powered By Fighter https://blog.csdn.net/qq_30115697/article/details/88865118

题意

原题传送门

Solution

由于最后求的是原点的细胞数,那么一定是先从原点向外扩展,再扩展回来到达原点。那么我们就可以把答案转化为从原点出发,经过 T T​ 时间回到原点的方案数。

于是我们考虑 d p dp ,设 f [ i ] [ j ] f[i][j] 表示用 i i 个维度,经过 2 j 2j 的时间回到原点的方案数(显然奇数时间答案为0)。那么我们考虑对于一个新的维度 i + 1 i+1 和新的时间 2 ( j + k ) 2(j+k) ,我们可以从所有时间中,用 2 k 2k 时间去第 i + 1 i+1 个维度,于是得到方案 C 2 ( j + k ) 2 k C_{2(j+k)}^{2k} ,同时这 2 k 2k 时间中,我们又需要分配 k k 的时间向外扩展,剩余 k k 的时间向内扩展,于是又有方案数 C 2 k k C_{2k}^{k} ,所以可以得出转移方程:
f [ i + 1 ] [ j + k ] = f [ i ] [ j ] C 2 ( j + k ) 2 k C 2 k k f[i+1][j+k]=f[i][j]*C_{2(j+k)}^{2k}*C_{2k}^{k}
于是进行一遍预处理,复杂度 O ( n 3 ) O(n^3) ,然后 O ( 1 ) O(1) 处理每个询问。总复杂度 O ( n 3 + Q ) O(n^{3}+Q)

Code

#include <bits/stdc++.h>
#define ll long long
#define P ((ll)1e9+7)
#define MAX 205
using namespace std;

ll C[MAX][MAX], f[MAX][MAX];

void init(){
	C[0][0] = C[1][1] = 1;
	for(int i = 1; i <= 200; i++){
		C[i][0] = 1;
		for(int j = 1; j <= i; j++){
			C[i][j] = (C[i-1][j-1]+C[i-1][j])%P;
		}
	}
}

int main()
{
	init();
	f[0][0] = 1;
	for(int i = 0; i <= 100; i++){
		for(int j = 0; j <= 100; j++){
			for(int k = 0; k+j <= 100; k++){
				f[i+1][j+k] += f[i][j]*C[2*(j+k)][2*k]%P*C[2*k][k]%P;
				f[i+1][j+k] %= P;
			}
		}
	}
	int t, n, T;
	cin >> t;
	while(t--){
		scanf("%d%d", &n, &T);
		if(T&1) puts("0");
		else
			printf("%lld\n", f[n][T/2]);
	}
	
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_30115697/article/details/88865118