zoukankan      html  css  js  c++  java
  • 【bzoj 3622】已经没有什么好害怕的了

    题目

    看到这个数据范围就发现我们需要一个(O(n^2))的做法了,那大概率是(dp)

    看到恰好(k)个我们就知道这基本是个容斥了

    首先解方程发现我们需要使得(a>b)的恰好有(frac{n+k}{2})

    如果不整除我们直接输出(0)就好了

    之后开始使用套路,直接广义容斥

    [ans=sum_{i=k}^n(-1)^{i-k}inom{i}{k}g_i ]

    (g_i)表配出至少(i)(a>b)的情况

    显然我们现在需要一个(dp)来算一下(g)

    首先发现两个数组是没有顺序的,所以先习惯性排个序

    (dp_{i,j})表示从(a)数组的前(i)个数中,已经配出(j)(a>b)的方案数

    边界(dp_{0,0}=1)

    我们排序的作用这个时候就体现出来了,我们设(d_i)表示满足(b_j<a_i)的最大的(j)

    由于(a,b)两个数组都是有序的,我们知道(d_i)肯定是单调不降的

    于是有这样的方程

    [dp_{i,j}=dp_{i-1,j}+max(d_i-(j-1),0)dp_{i-1,j-1} ]

    就是考虑对于第(i)个数满足(a>b)的只有(d_i)个,减去和前(i-1)个匹配的(j-1)个,剩下的我们随便找出一个来匹配就好了

    之后(g_i=dp_{n,i}(n-i)!),就是让没有满足(a<b)的那些随便匹配一下就好

    代码

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #define re register
    #define LL long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    #define pt putchar(1),puts("")
    const int maxn=2e3+5;
    const int mod=1e9+9;
    inline int read() {
    	char c=getchar();int x=0;while(c<'0'||c>'9') c=getchar();
    	while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();return x;
    }
    int n,k;
    int dp[maxn][maxn];
    int a[maxn],b[maxn];
    int fac[maxn],inv[maxn];
    inline LL ksm(LL a,int b) {
    	LL S=1;
    	while(b) {if(b&1) S=S*a%mod;b>>=1;a=a*a%mod;}
    	return S;
    } 
    inline int C(int n,int m) {
    	if(m>n) return 0;
    	return 1ll*fac[n]*inv[n-m]%mod*inv[m]%mod;
    }
    int main() {
    	n=read();k=read();
    	for(re int i=1;i<=n;i++) a[i]=read();
    	for(re int i=1;i<=n;i++) b[i]=read();
    	if((n+k)&1) {puts("0");return 0;}
    	std::sort(a+1,a+n+1),std::sort(b+1,b+n+1);
    	fac[0]=1;
    	for(re int i=1;i<=n;i++) fac[i]=(1ll*i*fac[i-1])%mod;
    	inv[n]=ksm(fac[n],mod-2);
    	for(re int i=n-1;i>=0;--i) inv[i]=(1ll*(i+1)*inv[i+1])%mod;
    	dp[0][0]=1;
    	for(re int i=1;i<=n;i++) {
    		int cnt=0;
    		for(re int j=1;j<=n;j++)
    			cnt+=(a[i]>b[j]);
    		for(re int j=0;j<=i;j++)
    			dp[i][j]=dp[i-1][j];
    		for(re int j=1;j<=i;j++)
    			dp[i][j]=(dp[i][j]+1ll*dp[i-1][j-1]*max(cnt-j+1,0)%mod)%mod;
    	}
    	k=(n+k)/2;
    	LL ans=0;
    	for(re int i=k;i<=n;i++)
    	if((i-k)&1) ans=(ans-1ll*C(i,k)*dp[n][i]%mod*fac[n-i]%mod+mod)%mod;
    		else ans=(ans+1ll*C(i,k)*dp[n][i]%mod*fac[n-i]%mod)%mod;
    	printf("%d
    ",(int)ans);
    	return 0;
    }
    
  • 相关阅读:
    【中文分词】条件随机场CRF
    【中文分词】最大熵马尔可夫模型MEMM
    【中文分词】二阶隐马尔可夫模型2-HMM
    【中文分词】隐马尔可夫模型HMM
    Elasticsearch的CRUD:REST与Java API
    d3的比例尺和坐标轴
    webpack DllPlugin的用法
    webpack单独启动目录方法
    d3的常用方法和数据类型
    d3中的enter,exit,update概念
  • 原文地址:https://www.cnblogs.com/asuldb/p/10632601.html
Copyright © 2011-2022 走看看