by组合计数

· · 个人记录

由于组合计数水平过低连黄题都切不掉了QWQ,故作此笔记。

1. 组合数的一些公式

2.一些常见问题

3.一些例题

1.P6475 [NOI Online #2 入门组] 建设城市

题目分析
观察题目,注意到题目中的x,y 两座楼可以在同侧,也可以在异侧,所以要先对大前提分讨。同时注意到值域m \in [1,10^5] 所以可以枚举地标高度。

总结: 对于问题,合理的将问题拆解,进行分类讨论或是分步计算,利用计数原理统计计数。

Code

#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=3e5+7;
const int mod=998244353;
int fastpow(int x,int n){
    int res=1;
    while(n){
        if(n&1) res=res*x%mod;
        x=x*x%mod,n=(n>>1);
    }
    return res;
}
int inverse(int x) {return fastpow(x,mod-2);}
int fac[N];
void init() {fac[0]=1;for(int i=1;i<N;i++) fac[i]=fac[i-1]*i%mod;}
int C(int n,int m){//C_n^m
    return fac[n]*inverse(fac[m])%mod*inverse(fac[n-m])%mod;
}
int n,m,x,y;
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    init();
    cin>>m>>n>>x>>y;
    int res=0;
    if(x<=n&&n<y){
        for(int i=1;i<=m;i++){
            int a=C(x-1+i-1,x-1)*C(m-i+1+n-x-1,n-x)%mod,b=C(y-1-n+m-i+1-1,y-1-n)*C(2*n-y+i-1,2*n-y)%mod;
            res=res+a*b%mod;
        }
    }else{
        if(x>n&&y>n) x=x-n,y=y-n;
        for(int i=1;i<=m;i++){
            int a=C(x-1+i-1,x-1)*C(n-y+m-i,n-y)%mod;
            res=(res+a)%mod;
        }
        res=res*C(n+m-1,n)%mod;
    }
    cout<<res%mod<<"\n";
    return 0;
}