【BZOJ3622】已经没有什么好害怕的了

Description

已经使 Modoka 有签订契约, 和自己一起战斗的想法后 , Mami 忽然感到自己不再是孤单一人了呢.
于是, 之前的谨慎的战斗作风也消失了 , 在对 Charlotte 的傀儡使用终曲——Tiro Finale后 , Mami 面临着即将被 Charlotte 的本体吃掉的局面.
这时, 已经多次面对过 Charlotte 的 Homura 告诉了学 OI 的你这样一个性质——Charlotte的结界中有两种具有能量的元素——一种是“糖果” , 另一种是“药片” , 每种各有 n 个. 在Charlotte 发动进攻前, “糖果”和“药片”会两两配对,若恰好“糖果”比“药片”能量大的组数比“药片”比“糖果”能量大的组数多 k 组, 则在这种局面下, Charlotte 的攻击会丢失,从而 Mami 仍有消灭 Charlotte 的可能. 你必须根据 Homura 告诉你的“糖果”和“药片”的能量的信息迅速告诉 Homura 这种情况的个数.

Input

第一行两个整数 n, k, 含义如题目描述.
接着第二行 n 个整数, 第 i 个数表示第 i 个糖果的能量.
第三行 n 个整数, 第 j 个数表示第 j 个药片 的能量.

Output

一个整数, 表示消灭 Charlotte 的情况个数.
答案可能会很大, 所以 mod (1 0^9 + 9)

Sample Input

4 2
5 35 15 45
40 20 10 30

Sample Output

4

我们先将糖果和药片分别排序,然后设t[i]表示比第i个糖果能量小的编号最大的药片的编号。

f[i][j]表示前i个糖果,已经配对了j组“糖果>药片”的方案数。f[i][j]=f[i-1][j]+max\left ( 0, \right t[i]-j+1)\cdot f[i-1][j-1]

然后剩下的糖果在随意分配,也就是说f[n][j] *=(n-j)!

然后我们的答案就是糖果>药片的组数刚好为(n+k)/2的方案数。

因为f[n][i]表示的是至少有i组糖果>药片的方案数,所以我们要容斥。设容斥系数为g[i],则g[(n+k)/2]=1,g[i]=-\sum _{j=(n+k)/2}^{i-1}g[j]\cdot C_{i}^{j},然后答案就是\sum _{i=(n+k)/2}^{n}f[n][i]\cdot g[i]

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<ctime>
#define ll long long
#define N 2005
#define mod 1000000009

using namespace std;
inline int Get() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}while('0'<=ch&&ch<='9') {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}return x*f;}

int n;
int k;
int a[N],b[N];
int t[N];
ll f[N][N],ans,fac[N];
ll g[N],c[N][N];
int main() {
	n=Get(),k=Get();
	for(int i=1;i<=n;i++) a[i]=Get();
	for(int i=1;i<=n;i++) b[i]=Get();
	sort(a+1,a+1+n);
	sort(b+1,b+1+n);
	if((n-k)&1)	{cout<<0;return 0;}
	k=(n+k)/2;
	int tem=0;
	for(int i=1;i<=n;i++) {
		while(tem<n&&a[i]>b[tem+1]) tem++;
		t[i]=tem;
	}
	f[0][0]=1;
	for(int i=1;i<=n;i++) {
		f[i][0]=1;
		for(int j=1;j<=n;j++) {
			f[i][j]=f[i-1][j];
			if(t[i]>=j) {
				(f[i][j]+=f[i-1][j-1]*(t[i]-j+1)%mod)%=mod;
			}
		}
	}
	fac[0]=1;
	for(int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
	for(int i=0;i<=n;i++) {
		f[n][i]=f[n][i]*fac[n-i]%mod;
	}
	c[0][0]=1;
	for(int i=1;i<=n;i++)
		for(int j=0;j<=i;j++)
			c[i][j]=(!j||i==j)?1:(c[i-1][j-1]+c[i-1][j])%mod;
	g[k]=1;
	for(int i=k+1;i<=n;i++) {
		for(int j=k;j<i;j++) {
			g[i]=(g[i]-g[j]*c[i][j]%mod+mod)%mod;
		}
	}
	for(int i=k;i<=n;i++) {
		ans=(ans+g[i]*f[n][i]%mod+mod)%mod;
	}
	cout<<ans;
	return 0;
}

 

posted @ 2018-10-07 08:37  hec0411  阅读(205)  评论(0编辑  收藏  举报