zoukankan      html  css  js  c++  java
  • [学习笔记]二项式反演

    • 例题:[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}inom{k}{i}g(k) ]

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

    • 二项式反演公式:

      [a_n=sum_{k=0}^{n}inom{n}{k}b_kLeftrightarrow b_n=sum_{k=0}^{n}(-1)^{n-k}inom{n}{k}a_k ]

      证明:略

    • 例题公式:

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

    #include <bits/stdc++.h>
    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<maxn;++i) fac[i]=fac[i-1]*i%mod;
        inv[maxn-1]=qpow(fac[maxn-1],mod-2);
        for(ll i=maxn-2;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<n;++i) scanf("%d",&x);
        for(ll i=2;i<=k;++i){
            if((k-i)%2==0){
                ans=(ans+c(k,i)*i%mod*qpow(i-1,n-1)%mod)%mod;
            }else{
                ans=(ans-c(k,i)*i%mod*qpow(i-1,n-1)%mod+mod)%mod;
            }
        }
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    Android ArrayAdapter使用
    Android 更改字体
    C# CRC16校验码 1.0
    获取当前主题颜色 Flutter
    C# 每个字节接受 处理串口数据 的方法
    C# CRC
    char* 与 string 互转
    typeof 子类获取父类
    flutter Row 垂直或水平放置多个widget
    flutter 容器 几种写法
  • 原文地址:https://www.cnblogs.com/smallocean/p/11585026.html
Copyright © 2011-2022 走看看