【BZOJ3622】已经没有什么好害怕的了
Description
Input
Output
Sample Input
4 2
5 35 15 45
40 20 10 30
5 35 15 45
40 20 10 30
Sample Output
4
HINT
输入的2*n个数字保证全不相同。
题意:给定a数组和b数组,大小都为N,现在让你两两配对,使得a>b个个数=(N+K)/2; a<b的个数=(N-K)/2;
思路:用容斥来求。 我们假设a>b为A情况,a<b为B情况。先让ab数组分别排序; f[i][j]表示前i个a数组至少存在j个A情况的方案数,那么可以得到f的递推式。 最后用容斥来累加答案。
推荐CQZhangYU的博客。
#include<bits/stdc++.h> #define ll long long #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; const int maxn=2010; const int Mod=1e9+9; int C[maxn][maxn],f[maxn][maxn],a[maxn],b[maxn],jc[maxn],ans; int main() { int N,K; scanf("%d%d",&N,&K); jc[0]=1; rep(i,1,N) jc[i]=(ll)jc[i-1]*i%Mod; rep(i,0,N){ C[i][0]=1; rep(j,1,i) C[i][j]=(C[i-1][j]+C[i-1][j-1])%Mod; } rep(i,1,N) scanf("%d",&a[i]); rep(i,1,N) scanf("%d",&b[i]); sort(a+1,a+N+1) ;sort(b+1,b+N+1); f[0][0]=1; rep(i,1,N){ int pos=upper_bound(b+1,b+N+1,a[i])-b; pos--; rep(j,1,i){ f[i][j]=(f[i-1][j]+(ll)f[i-1][j-1]*max(pos-j+1,0)%Mod)%Mod; } f[i][0]=f[i-1][0]; } if((N+K)%2==1) return puts("0"),0; K=(N+K)/2; rep(i,K,N){ f[N][i]=(ll)f[N][i]*jc[N-i]%Mod; if((i-K)&1) ans=((ans-(ll)f[N][i]*C[i][K]%Mod)%Mod+Mod)%Mod; else ans=(ans+(ll)f[N][i]*C[i][K]%Mod)%Mod; } printf("%lld ",(ans%Mod+Mod)%Mod); return 0; }