#卡特兰数,排列组合#洛谷 5014 水の三角(修改版)
分析
先不考虑横叉边,如果只有斜边,那么就是卡特兰数的形式,\(\binom{n+m}{n}-\binom{n+m}{m+1}\)
证明方式就是转化为 \((0,0)\) 走到 \((n,m)\) 不能跨过 \(y=x\),因为 \(m\leq n\),所以 \(m\) 多走的一步都能转化为不合法的方案。
再看回来横叉边就是走 \(i\) 个横叉边,那么 \((n,m)\) 就变成了 \((n-i,m-i)\) 就再枚举选多少个横叉边排列组合即可
代码
#include <iostream>
#include <cmath>
using namespace std;
const int N=2000011,mod=998244353;
typedef long long lll;
int inv[N],fac[N],k,ans,T; lll n,m;
int c(int n,int m){return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;}
int main(){
ios::sync_with_stdio(0);
inv[0]=inv[1]=fac[0]=fac[1]=1;
for (int i=2;i<N;++i) inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
for (int i=2;i<N;++i) fac[i]=1ll*fac[i-1]*i%mod,inv[i]=1ll*inv[i-1]*inv[i]%mod;
for (cin>>T;T;--T){
cin>>n,m=sqrt(2*n);
while (m*(m+1)<2*n) ++m;
k=n-m*(m-1)/2,--m,--k,ans=0;
for (int i=0;i<=k;++i)
ans=(ans+1ll*c(m+k-i,i)*(c(m+k-i*2,m-i)-c(m+k-i*2,m-i+1)+mod))%mod;
cout<<ans<<endl;
}
return 0;
}