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个数字保证全不相同。
还有输入应该是第二行是糖果,第三行是药片
Source
DP+容斥
http://www.cnblogs.com/dyllalala/p/3900077.html
f[i][j]表示前i个里面有j个a>b的方案,其他不管
然后容斥
dp[n][i]=f[n][i]*(n-i)!-dp[n][j]*C[j][i](i+1<=j<=n)
(n-i)!表示剩下的乱放
f[n][j]表示实际多算的, 乘上组合数表示j个放到前i个的方案数
66666666666666
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2010;
const int mod = 1e9 + 9;
int n, m, dp[maxn][maxn], C[maxn][maxn], a[maxn], b[maxn], nxt[maxn], fac[maxn];
inline void init()
{
for( int i = 0 ; i <= n ; i++ )
{
C[ i ][ 0 ] = 1;
for( int j = 1 ; j <= i ; j++ )
C[ i ][ j ] = ( C[ i - 1 ][ j - 1 ] + C[ i - 1 ][ j ] ) % mod;
}
fac[ 0 ] = 1;
for( int i = 1 ; i <= n ; i++ ) fac[ i ] = 1ll * fac[ i - 1 ] * i % mod;
}
int main()
{
scanf( "%d%d", &n, &m );
if( n - m & 1 ) return printf( "0\n" ), 0;
m = n + m >> 1;
init();
for( int i = 1 ; i <= n ; i++ ) scanf( "%d", &a[ i ] );
for( int i = 1 ; i <= n ; i++ ) scanf( "%d", &b[ i ] );
sort( a + 1, a + n + 1 );
sort( b + 1, b + n + 1 );
int now = 0;
for( int i = 1 ; i <= n ; i++ )
{
while( now < n && a[ i ] > b[ now + 1 ] ) now++;
nxt[ i ] = now;
}
dp[ 0 ][ 0 ] = 1;
for( int i = 1 ; i <= n ; i++ )
for( int j = 0 ; j <= i ; j++ )
{
dp[ i ][ j ] = dp[ i - 1 ][ j ];
if( j && nxt[ i ] - j + 1 > 0 )
( dp[ i ][ j ] += 1ll * dp[ i - 1 ][ j - 1 ] * ( nxt[ i ] - j + 1 ) % mod ) %= mod;
}
for( int i = n ; i >= m ; i-- )
{
dp[ n ][ i ] = 1ll * dp[ n ][ i ] * fac[ n - i ] % mod;
for( int j = i + 1 ; j <= n ; j++ ) ( dp[ n ][ i ] -= 1ll * dp[ n ][ j ] * C[ j ][ i ] % mod ) %= mod;
}
return printf( "%d\n", ( dp[ n ][ m ] + mod ) % mod );
}