【题解】Hikari与组合数
题目背景
\(Tairitsu\)给\(Hikari\)出了一个组合数的题
题目描述
求出\(\begin{aligned}\sum_{i=0}^xC_{x}^i*C_{y}^{z+i}\%998244353\end{aligned}\)
Hikari稍微想了想这不是个傻叉的杨辉三角吗,但她看到数据范围后就更懵逼了,于是她来寻求你的帮助。
输入格式
第一行一个整数\(T\)表示数据组数。
接下来\(T\)行,每行分别有三个整数\(x\),\(y\),\(z\)。
输出格式
共\(T\)行对应\(T\)个询问。
样例输入
2
3 5 2
400 200 100
样例输出
56
282195585
样例解释
Cirno都能算的出来
数据范围
对于\(10%\)的数据 \(T=10,x,y,z<=10\)。
对于\(30%\)的数据 \(T=10,x,y,z<=1000\)。
对于另外\(20%\)的数据满足\(T=1,x,y,z<=1000000\)。
对于另外\(10%\)的数据满足\(x=0\)。
对于另外\(10%\)的数据满足\(x=1\)。
对于\(100%\)的数据满足\(T<=10000,0<=x,y,z<=1000000\),且保证\(y>=z\)
前置芝士
范德蒙德卷积
\(\begin{aligned}\sum_{i=0}^k{C_n^iC_{m}^{k-i}}=C_{n+m}^{k}\end{aligned}\)
从意义上理解即可,也就是从数量为\(n\)和\(m\)的两个堆中一共选择\(k\)个物品这两个堆在实际意义上也可以不存在。
有了这个公式你就可以一步得到结论,最后就求\(\begin{aligned}C_{x+y}^{x+z}\%998244353\end{aligned}\)即可
常用结论:\(\begin{aligned}\sum_{i=1}^n{C_n^iC_{n}^{i-1}}=C_{2n}^{n-1}\end{aligned}\)
简单的证明:
\(\binom{2n}{n-1}=\sum_{i=0}^{n}{\binom{n}{i}\binom{n}{n-1-i}}=\sum_{i=0}^{n}{\binom{n}{i}\binom{n}{i+1}}=\sum_{i=1}^{n}\binom{n}{i}\binom{n}{i-1}\)
\(\begin{aligned}\sum_{i=0}^n{C_n^i}^2=C_{2n}^{n}\end{aligned}\)
\(\begin{aligned}\sum_{i=1}^m{C_n^iC_m^{i}}=C_{n+m}^{m}\end{aligned}\)
读者自证不难
#include<bits/stdc++.h>
#define LL long long
using namespace std;
/*Grievous Lady*/
template <typename T> void read(T & t){
t = 0;int f = 1;char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-')f =- 1;ch = getchar();}
do{t = t * 10 + ch - '0';ch = getchar();}while(ch >= '0' && ch <= '9');t *= f;
}
#define mod 998244353
const int kato = 1e6 + 1;
LL yuni[kato * 2];
inline LL quick_pow(LL a , LL b){
LL res = 1;
for(; b ; b >>= 1 , a = a * a % mod){
if(b & 1){
res = res * a % mod;
}
}
return res % mod;
}
inline LL c(LL x , LL y){
if(x < y){
return 0;
}
return yuni[x] * quick_pow(yuni[y] * yuni[x - y] % mod , mod - 2) % mod;
}
inline LL lucas(LL x , LL y){
if(y == 0) return 1;
return c(x % mod , y % mod) * lucas(x / mod , y / mod) % mod;
}
LL t , x , y , z;
inline int Ame_(){
read(t);
yuni[0] = yuni[1] = 1;
for(int i = 1;i <= 2 * kato;i ++){
// cout << "QAQ" << "\n";
yuni[i] = (yuni[i - 1] * i) % mod;
}
// cout << yuni[3] << ' ' << yuni[5] << ' ';
for(; t --> 0 ;){
LL ans = 0;
read(x);read(y);read(z);
ans = lucas(x + y , x + z);
printf("%lld\n" , ans % mod);
}
return 0;
}
int Ame__ = Ame_();
int main(){;}