题目描述
有N棵高度不一样的树要种成一行,为了让种树更加有艺术性,制定一个种树规则,希望从左边看过去只能看到L棵树,从右边看过去只能看到R棵树,请问有多少种不同的种树方案。
输入格式
输入包含多组数据。
首先第一行包含一个整数t,表示数据的组数。
之后t行,每行包含三个数N,L,R,以空格隔开,表示树的棵数N以及从左边看过去的棵数L和从右边看过去的棵数R。
输出格式
共t行,每行一个数,表示每组数据所对应的种树的方案数。答案可能很大,请对 998244353取模。
样例
样例输入
2
4 1 2
4 2 1
样例输出
2
2
设 dp[i][j][k] 表示前i棵树左边看过去能看到j棵,右边看过去能看到k棵。
考虑最低的树,有三种情况:
1:放在最左边,拿走后只影响左看右
2:放在最右边,拿走之后只影响右看左
3:放在中间都不影响,有i-2种放法
所以 dp[i][j][k]=dp[i-1][j][k-1]+dp[i-1][j-1][k]+dp[i-1][j][k]*(i-1)
其中 当j == i || k == i 时 dp[i][j][k]=1
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cctype>
#include<iomanip>
using namespace std;
const int M=205,Mod=998244353;
int n,l,r,T;
long long dp[M][M][M];
int main(){
scanf("%d",&T);
for(int i=1;i<=200;i++)
for(int j=1;j<=i;j++)
for(int k=1;k<=i-j+1;k++){
if(k==i||j==i)
dp[i][j][k]=1;
else
dp[i][j][k]=(dp[i-1][j-1][k]+dp[i-1][j][k-1]+(dp[i-1][j][k]*(i-2))%Mod)%Mod;
}
while(T--){
scanf("%d %d %d",&n,&l,&r);
printf("%lld\n",dp[n][l][r]);
}
return 0;
}
其实可以两层循环,但我不会,在网上也没找到。