我们先设 d p i , j dp_{i,j} dpi,j 表示到 i i i 使得 a > b a>b a>b 的个数为 j j j 的方案数。
显然 d p i , j = d p i − 1 , j + d p i − 1 , j − 1 × ( b i g i − j + 1 ) dp_{i,j}= dp_{i-1,j}+dp_{i-1,j-1}\times (big_i-j+1) dpi,j=dpi−1,j+dpi−1,j−1×(bigi−j+1),其中 b i g i big_i bigi 为在 b b b 中比 a i a_i ai 的个数。
我们在按套路设 f i f_i fi 表示钦定(即只要达到目标后可以继续随便填) a > b a>b a>b 个数为 i i i 的方案数。 g i g_i gi 表示恰好 a > b a>b a>b 个数为 i i i 的方案数。
其中 f m = d p n , m × ( n − m ) ! f_m=dp_{n,m}\times (n-m)! fm=dpn,m×(n−m)!
考虑二项式反演, g i = ∑ i = m n ( − 1 ) i − m C i m f ( i ) g_i= \sum_{i=m}^{n} (-1)^{i-m}C_{i}^{m}f(i) gi=∑i=mn(−1)i−mCimf(i)
最后得: g i = ∑ i = m n ( − 1 ) i − m C i m × d p n , i × ( n − i ) ! g_i= \sum_{i=m}^{n} (-1)^{i-m}C_{i}^{m}\times dp_{n,i}\times(n-i)! gi=∑i=mn(−1)i−mCim×dpn,i×(n−i)!
时间复杂度: O ( n 2 ) O(n^2) O(n2)
#include
#define For(i,a,b) for ( int i=(a);i<=(b);i++ )
#define Dow(i,b,a) for ( int i=(b);i>=(a);i-- )
#define GO(i,x) for ( int i=head[x];i;i=e[i].nex )
#define mem(x,s) memset(x,s,sizeof(x))
#define cpy(x,s) memcpy(x,s,sizeof(x))
#define YES return puts("YES"),0
#define NO return puts("NO"),0
#define GG return puts("0"),0
#define pb push_back
#define lowbit(x) x&(-x)
#define int long long
using namespace std;
inline int read()
{
int sum=0,ff=1; char ch=getchar();
while(!isdigit(ch))
{
if(ch=='-') ff=-1;
ch=getchar();
}
while(isdigit(ch))
sum=sum*10+(ch^48),ch=getchar();
return sum*ff;
}
const int mod=1e9+7;
const int mo=1e9+9;
const int N=2e3+5;
inline int min(int x,int y) {return (x>y)?y:x;}
inline int max(int x,int y) {return (x<y)?y:x;}
inline void Add(int &x,int y)
{
if(y>=mo) y%=mo;
x+=y;
if(x>=mo) x-=mo;
}
int n,m,a[N],b[N],C[N][N],fac[N],ans;
int dp[N][N],f[N],g[N];
signed main()
{
n=read(),m=read();
if((n-m)&1) GG;
m=(n+m)>>1ll;
For(i,1,n) a[i]=read();
For(i,1,n) b[i]=read();
sort(a+1,a+n+1);
sort(b+1,b+n+1);
C[0][0]=1,fac[0]=1;
For(i,0,n) dp[i][0]=1;
int p=0;
For(i,1,n)
{
while(p<n&&b[p+1]<a[i]) p++;
For(j,1,n) Add(dp[i][j],dp[i-1][j]+dp[i-1][j-1]*(p-j+1)%mo);
}
For(i,1,n)
{
C[i][0]=1;
fac[i]=fac[i-1]*i%mo;
For(j,1,i) Add(C[i][j],C[i-1][j-1]+C[i-1][j]);
}
int ans=0;
For(i,m,n)
{
if((i-m)&1ll) Add(ans,-1*C[i][m]*fac[n-i]%mo*dp[n][i]%mo+mo);
else Add(ans,C[i][m]*fac[n-i]%mo*dp[n][i]%mo);
}
printf("%lld\n",(ans+mo)%mo);
return 0;
}