经典容斥+排列组合——cf1342E

Posted zsben991126

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了经典容斥+排列组合——cf1342E相关的知识,希望对你有一定的参考价值。

/*
设每行都有一个,每列上每多一个攻击对就会+1,
列上多了k个,那么只有n-k列上有棋子C(n,n-k)
问题变成将n个棋子放在n-k列上,且每列必须有一个,每行必须有且仅有一个的方案数
容斥:
    ans=将n个棋子随便放在某一列 pow(n-k,n)
    -有一个空行 pow(n-k-1,n)C(n-k,1) 
     +有两个空行 pow(n-k-2,n)C(n-k,2)
     ...
最后,在n行里面选n-k行的方案数是C(n,n-k)
如果是n列里选n-k列,则方案数还要再*2
所以答案是ans*C(n,n-k)*2 
*/
#include<bits/stdc++.h>
using namespace std;
#define ll long long 
#define mod 998244353
#define N 200006

ll n,k,F[N],inv[N];

ll Pow(ll a,ll b){
    ll res=1;
    while(b){
        if(b%2)res=res*a%mod;
        b>>=1;a=a*a%mod;
    }
    return res;
}
void init(){
    F[0]=inv[0]=1;
    for(int i=1;i<=n;i++){
        F[i]=F[i-1]*i%mod;
        inv[i]=Pow(F[i],mod-2);
    }
}
ll C(ll a,ll b){
    if(a<b)return 0;
    if(a==b || b==0)return 1; 
    return F[a]*inv[b]%mod*inv[a-b]%mod;
}
ll calc(ll i){//有i个空行的情况
    ll res=Pow(n-k-i,n);
    res=res*C(n-k,i)%mod; 
    return res;
}

int main(){
    cin>>n>>k;
    init();
    if(k>=n){puts("0");return 0;}
    else if(k==0){
        cout<<F[n]<<"
";
    }else {
        ll ans=Pow(n-k,n);
        int sign=1;
        for(int i=1;i<=n-k-1;i++){
            sign*=-1;
            ans=(ans+sign*calc(i)%mod+mod)%mod;
        }
        cout<<ans*C(n,n-k)*2%mod<<
;
    }
}

 

以上是关于经典容斥+排列组合——cf1342E的主要内容,如果未能解决你的问题,请参考以下文章

容斥原理解一般不定方程——cf451E经典题

CF 317 A. Lengthening Sticks(容斥+组合数学)

CF1096E The Top Scorer 组合数 容斥

排列组合-容斥原理

排列组合或容斥原理

专题计数问题(排列组合,容斥原理,卡特兰数)