题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=3622
题解
对糖果和药片都排一遍序,设表示对于号糖果,比他小的药片有多少个,表示对于前个糖果和对应的个药片,糖果比药片至少多个的方案数是多少,不考虑其他的情况,dp转移。
最后容斥求出糖果比药片恰好多个的方案数
代码
#include <cstdio>
#include <algorithm>
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
const int maxn=2000;
const int mod=1000000009;
int n,k,candy[maxn+10],pill[maxn+10],cnt[maxn+10],f[maxn+10][maxn+10],fac[maxn+10],ifac[maxn+10];
int C(int a,int b)
{
if(b>a)
{
return 0;
}
return 1ll*fac[a]*ifac[b]%mod*ifac[a-b]%mod;
}
int main()
{
n=read();
k=read();
if((n-k)&1)
{
puts("0");
return 0;
}
k=((n-k)>>1)+k;
for(int i=1; i<=n; ++i)
{
candy[i]=read();
}
for(int i=1; i<=n; ++i)
{
pill[i]=read();
}
fac[0]=1;
for(int i=1; i<=n; ++i)
{
fac[i]=1ll*fac[i-1]*i%mod;
}
ifac[0]=ifac[1]=1;
for(int i=2; i<=n; ++i)
{
ifac[i]=1ll*(mod-mod/i)*ifac[mod%i]%mod;
}
for(int i=1; i<=n; ++i)
{
ifac[i]=1ll*ifac[i]*ifac[i-1]%mod;
}
std::sort(candy+1,candy+n+1);
std::sort(pill+1,pill+n+1);
int now=0;
for(int i=1; i<=n; ++i)
{
while((now<n)&&(pill[now+1]<candy[i]))
{
++now;
}
cnt[i]=now;
}
f[0][0]=1;
for(int i=1; i<=n; ++i)
{
for(int j=0; j<=i; ++j)
{
f[i][j]=f[i-1][j];
if((j>0)&&(cnt[i]-j+1>0))
{
f[i][j]=(f[i][j]+1ll*f[i-1][j-1]*(cnt[i]-j+1))%mod;
}
}
}
int ans=0;
for(int i=k; i<=n; ++i)
{
ans=(ans+(((i-k)&1)?(mod-1ll):1ll)*C(i,k)%mod*f[n][i]%mod*fac[n-i])%mod;
}
printf("%d\n",ans);
return 0;
}