【题解】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(){;}
posted @ 2020-08-02 16:36  Ame_sora  阅读(181)  评论(1编辑  收藏  举报