zoukankan      html  css  js  c++  java
  • P4859 已经没有什么好害怕的了

    题意

    (a)(b) 两个长度为 (n) 的序列,其中元素两两配对, (a>b) 的配对需比 (a<b) 的配对多恰好 (k) 个,求方案数

    Solution

    我们设 (f_{i,j}) 为前 (i)(a) 中,选了 (j)(a>b) 的方案数

    可得状态转移方程:

    [f_{i,j}=f_{i-1,j}+f_{i-1,j-1}*(l_i-j+1) ]

    (l_i) 表示离 (a_i) 最近的一个 (b)

    再设 (g_i)(geq i) 个的配对方案数, (h_i) 为恰好 (=i) 个的方案数,可得 (g_i=f_{n,i}*(n-i)!)

    且容易得, (f_i)(g_j) 中算了 ((^i_j))

    所以,得到:

    [g(k)=sumlimits_{i=k}^ndbinom ikf(i) ]

    由二项式反演,得:

    [f(k)=sumlimits_{i=k}^n(-1)^{i-k}dbinom ikg(i) ]

    代码

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<iostream>
    #define ll long long
    
    using namespace std;
    const int N=2005,mod=1e9+9;
    int n,k,a[N],b[N];
    ll f[N][N],fac[N],inv[N],fac_inv[N];
    int g[N];
    
    inline int read(){
        int x=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
        while(isdigit(ch)){x=x*10+(ch^48);ch=getchar();}
        return x*f;
    }
    
    inline void init(){
        inv[1]=1;fac[0]=fac_inv[0]=1;
        for(int i=1;i<=n;i++){
            if(i!=1) inv[i]=(mod-mod/i)*inv[mod%i]%mod;
            fac[i]=fac[i-1]*i%mod;
            fac_inv[i]=fac_inv[i-1]*inv[i]%mod;
        }
    }
    
    inline ll C(int n,int m){
        return fac[n]*fac_inv[m]%mod*fac_inv[n-m]%mod;
    }
    
    int main(){
        n=read();k=read();
        if((n+k)&1){
            puts("0");
            return 0;
        }
        k+=(n-k)/2;
        for(int i=1;i<=n;i++) a[i]=read();
        for(int i=1;i<=n;i++) b[i]=read();
        sort(a+1,a+n+1);
        sort(b+1,b+n+1);
        init();
        int now=0;
        for(int i=1;i<=n;i++){
            while(now<n&&a[i]>b[now+1]) now++;
            g[i]=now;
        }
        for(int i=0;i<=n;i++) f[i][0]=1;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=g[i];j++)
                f[i][j]=(f[i-1][j]+f[i-1][j-1]*(g[i]-j+1)%mod)%mod;
        ll ans=0;
        for(int i=k;i<=n;i++)
            ans=(ans+(((i-k)&1)?-1:1)*fac[n-i]*f[n][i]%mod*C(i,k)%mod+mod)%mod;
        printf("%lld
    ",ans);
        return 0;
    }
    
  • 相关阅读:
    PHP防跨站之open_basedir目录设置
    在线Jupyter平台,验证手机号可免费使用
    wget命令之用户密码cookies断点续传指定类型整站下载
    linux控制台输出到文件
    结构体取变量
    常用编码解码识别
    #define和const
    做一个自己的清理临时文件的小程序(附成品&升级版)
    C盘清理/瘦身
    修复Word启动失败 报错WPS32
  • 原文地址:https://www.cnblogs.com/jasony/p/13641972.html
Copyright © 2011-2022 走看看