[DP 容斥原理] BZOJ3622 已经没有什么好害怕的了

传送门:http://www.cnblogs.com/dyllalala/p/3900077.html

比较好的DP题

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define P 1000000009
using namespace std;
typedef long long ll;

inline char nc(){
	static char buf[100000],*p1=buf,*p2=buf;
	if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); return EOF; }
	return *p1++;
}

inline void read(ll &x){
	char c=nc(),b=1;
	for (;!(c>='0' && c<='9');c=nc()) if(c=='-') b=-1;
	for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;
}

ll n,K,s;
ll a[2005],b[2005];
ll f[2005][2005];
ll fac[2005],C[2005][2005];
ll next[2005];

inline void Pre(){
	fac[0]=1;
	for (int i=1;i<=2000;i++)
		(fac[i]=fac[i-1]*i)%=P;
	C[0][0]=1;
	for (int i=0;i<=2000;i++)
	{
		C[i][0]=1; 
		for (int j=1;j<=i;j++)
			(C[i][j]=C[i-1][j-1]+C[i-1][j])%=P;
	}
}

int main()
{
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	Pre();
	read(n); read(K);
	if ((n+K)&1) return printf("0\n"),0;
	s=(n+K)/2;
	for (int i=1;i<=n;i++) read(a[i]);
	for (int i=1;i<=n;i++) read(b[i]);
	sort(a+1,a+n+1);
	sort(b+1,b+n+1);
	int j=0;
	for (int i=1;i<=n;i++)
	{
		while (j+1<=n && b[j+1]<a[i]) j++;
		next[i]=j;
	}
	f[0][0]=1;
	for (int i=1;i<=n;i++)
		for (int j=0;j<=i;j++)
		{
			f[i][j]=f[i-1][j];
			if (j && next[i]-j+1>0)
				(f[i][j]+=f[i-1][j-1]*(next[i]-j+1))%=P;
		}
	for (int i=n;i>=s;i--)
	{
		(f[n][i]*=fac[n-i])%=P;
		for (int j=i+1;j<=n;j++)
			(((f[n][i]-=f[n][j]*C[j][i])%=P)+=P)%=P;
	}
	printf("%lld\n",f[n][s]);
	return 0;
}


你可能感兴趣的:([DP 容斥原理] BZOJ3622 已经没有什么好害怕的了)