题目&&题解:点击打开链接
题意:
给你两个序列 a,b 每个序列共 nn 个数 , 数之间两两不同
问 a 与 b 之间有多少配对方案 使得 ai>bi的对数 比 bi>ai的恰好多 k对.
(1≤k≤n≤2000)
代码写得是真的丑,这么简单的题还调了好久!
一定要把容斥的每一个细节推清楚再写,否则边界写错了挺难查出的!
下次这种简单的(无代码量)题10分钟要写完调完!
用rep来define for可以减少代码量,码风转换中。。。。
mod是1e9+9幸好也是质数,否则要n^2递推组合数
#include<bits/stdc++.h>
using namespace std;
#define maxn 2020
#define rep(i,l,r) for(register int i = l ; i <= r ; i++)
#define rep2(i,l,r) for(register int i = l ; i >= r ; i--)
typedef long long ll;
const ll mod = 1e9 + 9;
ll f[maxn][maxn],F[maxn],inv[maxn],fac[maxn],ans;
int a[maxn],b[maxn],n,k;
inline void Add(ll &x,ll y){
x += y;
if ( x >= mod ) x -= mod;
else if( x < 0 ) x += mod;
}
ll power(ll x,int y){
ll res = 1;
while ( y ){
if ( y & 1 ) res = res * x % mod;
y >>= 1;
x = x * x % mod;
}
return res;
}
void init(){
inv[0] = fac[0] = 1;
rep (i,1,n) fac[i] = fac[i - 1] * i % mod;
inv[n] = power(fac[n],mod - 2);
rep2(i,n - 1,1) inv[i] = inv[i + 1] * (i + 1) % mod;
/* C[0][0] = 1;
rep (i, 1, n) {
C[i][0] = 1;
rep (j, 1, n)
C[i][j] = (C[i - 1][j] + C[i - 1][j - 1]) % mod;
}*/
}
ll C(int n,int m){
if ( !m || n == m ) return 1;
return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
int main(){
//freopen("input.txt","r",stdin);
scanf("%d %d",&n,&k);
// if ( (n + k) % 2 ){ printf("0\n"); return 0; }
rep (i,1,n) scanf("%d",&a[i]);
rep (i,1,n) scanf("%d",&b[i]);
init();
sort(a + 1,a + n + 1) , sort(b + 1,b + n + 1);
f[0][0] = 1 , k = (n + k) / 2;
rep (i,1,n){
int num = upper_bound(b + 1,b + n + 1,a[i]) - b - 1;
rep (j,0,num){
Add(f[i][j],f[i - 1][j]);
if ( j ) Add(f[i][j],f[i - 1][j - 1] * (num - j + 1) % mod);
}
}
/*rep (i,1,n){
rep (j,0,n){
cout<<f[i][j]<<" ";
}
cout<<endl;
}*/
rep (i,1,n) F[i] = f[n][i] * fac[n - i] % mod;
rep (i,k,n){
if ( (i - k) & 1 ) Add(ans,-C(i,k) * F[i] % mod);
else Add(ans,C(i,k) * F[i] % mod);
}
cout<<ans<<endl;
return 0;
}