来自FallDream的博客,未经允许,请勿转载,谢谢。
n<=2000
这题有点神....
先考虑dp,f[i][j]表示前i个中确定了j对a>b的方案数,令num[i]表示A[i]大于多少个B中的元素,那么
$f[i][j]=f[i-1][j]+f[i-1][j-1]*(num[i]-j+1)$
然后考虑去重,令F[i]表示全部确定之后恰好有i对a>b的方案数,那么$F[i]=f[n][i]*(n-i)!-sum_{j=i+1}^{n}F[j]*C(j,i)$
复杂度n^2
#include<algorithm> #include<iostream> #include<cstdio> #define MN 2000 #define mod 1000000009 using namespace std; inline int read() { int x = 0 , f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();} return x * f; } int p[MN+5],inv[MN+5],n,k,f[MN+5][MN+5],A[MN+5],B[MN+5],num[MN+5]; inline void R(int&x,int y){x+=y;x>=mod?x-=mod:0;} inline int C(int n,int m){return 1LL*p[n]*inv[m]%mod*inv[n-m]%mod;} int main() { n=read();k=read();if((n+k)&1) return 0*puts("0"); 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); for(int i=1;i<=n;++i) num[i]=upper_bound(B+1,B+n+1,A[i])-B-1; f[0][0]=p[0]=p[1]=inv[0]=inv[1]=1; for(int i=1;i<=n;++i) for(int j=0;j<=i;++j) { if(j&&num[i]-j+1>0) R(f[i][j],1LL*f[i-1][j-1]*(num[i]-j+1)%mod); R(f[i][j],f[i-1][j]); } for(int i=2;i<=n;++i) p[i]=1LL*p[i-1]*i%mod,inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod; for(int i=2;i<=n;++i) inv[i]=1LL*inv[i]*inv[i-1]%mod; for(int i=n-1;~i;--i) { f[n][i]=1LL*f[n][i]*p[n-i]%mod; for(int j=i+1;j<=n;++j) R(f[n][i],mod-(1LL*f[n][j]*C(j,i)%mod)); } printf("%d ",f[n][n+k>>1]); return 0; }