[学习笔记]二项式反演

[学习笔记]二项式反演

  • 例题:[King's Colors][https://vjudge.net/problem/Kattis-kingscolors]

    • 题意:n个点的树,用恰好k种颜色染色,并且要求相邻两个点不同。

    • 这题可以发现就是组合数学题,跟树的形状一点关系都没有。求最多用k种颜色染色的合法方案很容易:
      \[ f(n)=k(k-1)^{n-1} \]

    • 易得,令\(g(k)\)为恰好\(k\)种颜色的方案数
      \[ f(k)=\sum_{i=2}^{k}\binom{k}{i}g(k) \]

    • 答案要求\(g( n )​\) 这要用到二项式反演

  • 二项式反演公式:
    \[ a_n=\sum_{k=0}^{n}\binom{n}{k}b_k\Leftrightarrow b_n=\sum_{k=0}^{n}(-1)^{n-k}\binom{n}{k}a_k \]
    证明:略

  • 例题公式:

    \[ g(k)=\sum_{i=2}^{k}(-1)^{k-i}\binom{k}{i}f(i) \]

#include 
using namespace std;

typedef long long ll;
const int mod = 1e9+7;
const int maxn = 3000;
ll fac[maxn],inv[maxn];
ll qpow(ll x,ll n){
    ll res=1;
    while(n){
        if(n&1) res=x*res%mod;
        x=x*x%mod;
        n>>=1;
    }
    return res;
}
ll c(ll n,ll m){
    return fac[n]*inv[n-m]%mod*inv[m]%mod;
}
void init(){
    fac[0]=1;
    for(ll i=1;i=0;--i){
        inv[i]=inv[i+1]*(i+1ll)%mod;
    }
}
int main() {
    ll n,k;
    ll ans=0;
    init();
    scanf("%lld%lld",&n,&k);
    for(int i=1,x;i

你可能感兴趣的:([学习笔记]二项式反演)