#卡特兰数,排列组合#洛谷 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;
}
posted @ 2022-03-12 21:01  lemondinosaur  阅读(45)  评论(0编辑  收藏  举报