如果这篇博客帮助到你,可以请我喝一杯咖啡~
CC BY-NC-SA 4.0 (除特别声明或转载文章外)
很显然,题目等价于将三角形网格划分为若干个菱形的方案数,每个菱形由两个三角形组成,而这个方案又与 $a\times b\times c$ 的长方体中,堆叠了一些靠一墙角放置的 $1\times 1\times 1$ 的小正方体的方案数相等。
考虑每个位置的高度,问题等价于,给一个 $a\times b$ 的网格 $h$ 内填数,每个位置可以填 $[0,c]$ 中的整数,且要满足 $h_{i,j}\le h_{i+1,j}\land h_{i,j}\le h_{i,j+1}$ 的方案数。
设 $g_{i,j}=h_{i,j}+i$,则有 $g_{i,j}< g_{i+1,j}\land g_{i,j}\le g_{i,j+1}$,且所有满足 $g_{i,j}< g_{i+1,j}\land g_{i,j}\le g_{i,j+1}$ 且每个位置都在 $[1,a+c]$ 中的 $g$ 与 $h$ 一一对应。
我们发现,$g$ 是一个半标准杨表,根据钩长公式,我们知道,其填数方案数即为
\[\prod\limits_{i=1}^a\prod\limits_{j=1}^b\frac{a+c+j-i}{a-i+b-j+1}\\ =\prod\limits_{i=1}^a\prod\limits_{j=1}^b\frac{(a+c-i)+j}{(a+b-i+1)-j}\\ =\prod\limits_{i=1}^a\frac{(a+c+b-i)!(a-i)!}{(a+c-i)!(a+b-i)!}\\ =\frac{f(a+b+c-1)f(a-1)f(c-1)f(b-1)}{f(b+c-1)f(a+c-1)f(a+b-1)}\\ f(n)=\prod\limits_{i=1}^ni!\]预处理 $O(a+b+c)$,单次询问 $O(1)$。
#include<iostream>
using std::cin;
using std::cout;
int const mod=998244353;
int fac[3000010],f[3000010],iv[3000010],a,b,c;
int pow(int x,int y){
int res=1;
while(y){
if(y&1) res=1ll*res*x%mod;
x=1ll*x*x%mod,y>>=1;
}
return res;
}
int main(){
std::ios::sync_with_stdio(false),cin.tie(nullptr);
cin>>a>>b>>c;
int n=a+b+c;
fac[0]=f[0]=1;
for(int i=1;i<=n;i++) fac[i]=1ll*i*fac[i-1]%mod;
for(int i=1;i<=n;i++) f[i]=1ll*f[i-1]*fac[i]%mod;
iv[n]=pow(f[n],mod-2);
for(int i=n;i;i--) iv[i-1]=1ll*iv[i]*fac[i]%mod;
cout<<(1ll*f[n-1]*f[a-1]%mod*f[b-1]%mod*f[c-1]%mod*iv[a+b-1]%mod*iv[a+c-1]%mod*iv[b+c-1]%mod)<<'\n';
return 0;
}