CF2150B Grid Counting 题解
前置知识:乘法原理、组合数、乘法逆元。
题目大意
给出一个
对于每个
- 第
k 行中存在a_k 个黑格。 - 存在一个索引
i 使得\max(x_i,y_i)=k 。 - 存在一个索引
i 使得\max(x_i,n+1-y_i)=k 。
我们需要计算有多少种方案使得满足题目的条件。
思路
观察样例:
每个
我们注意到,第二个与第三个条件存在对称性。则对于更一般的情况,由对称性,我们先对于每个
Code
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e5+5,MOD=998244353;
int T,n;
int fac[N],inv[N],a[N],cnt[N];
int qpow(int x,int y)
{
int res=1;
while(y)
{
if(y&1)(res*=x)%=MOD;
(x*=x)%=MOD;
y>>=1;
}
return res;
}
void init()
{
fac[0]=1;
for(int i=1;i<N;i++)
fac[i]=fac[i-1]*i%MOD;
inv[N-1]=qpow(fac[N-1],MOD-2);
for(int i=N-2;i>=0;i--)
inv[i]=inv[i+1]*(i+1)%MOD;
}
inline int C(int n,int m){return n<m?0:fac[n]*inv[n-m]%MOD*inv[m]%MOD;}
signed main()
{
ios_base::sync_with_stdio(false),cin.tie(0),cout.tie(0);
init();
cin>>T;
while(T--)
{
memset(cnt,0,sizeof(cnt));
cin>>n;
int sum=0;
for(int i=1;i<=n;i++)
cin>>a[i],sum+=a[i];
if(sum!=n)
{
cout<<0<<'\n';
continue;
}
for(int k=1;k<=n;k++)
{
int val=n+2-2*k;
if(val<0)val=0;
cnt[k]=val;
}
int ans=1,used=0;
bool flag=1;
for(int k=n;k>=1;k--)
{
int can=cnt[k]-used;
if(can<0)can=0;
if(can<a[k])
{
flag=0;
break;
}
ans=ans*C(can,a[k])%MOD;
used+=a[k];
}
if(!flag)cout<<"0\n";
else cout<<ans%MOD<<'\n';
}
return 0;
}