您的位置:首页 > 其它

[bzoj3622]已经没有什么好害怕的了

2017-07-05 09:29 429 查看
来自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
[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
*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
[i]=1LL*f
[i]*p[n-i]%mod;
for(int j=i+1;j<=n;++j)
R(f
[i],mod-(1LL*f
[j]*C(j,i)%mod));
}
printf("%d\n",f
[n+k>>1]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: