题目链接

https://www.lydsy.com/JudgeOnline/problem.php?id=3622

题解

对糖果和药片都排一遍序,设cnt[i]cnt[i]表示对于ii号糖果,比他小的药片有多少个,f[i][j]f[i][j]表示对于前ii个糖果和对应的ii个药片,糖果比药片至少jj个的方案数是多少,不考虑其他的情况,dp转移f[i][j]f[i][j]
f[i][j]=f[i1][j]+f[i1][j1]×(cnt[i]j+1) f[i][j]=f[i-1][j]+f[i-1][j-1]\times (cnt[i]-j+1)
最后容斥求出糖果比药片恰好多kk个的方案数
ans=i=kn(1)ik(ik)f[n][i](ni)! ans=\sum_{i=k}^n (-1)^{i-k} \binom{i}{k} f[n][i] (n-i)!

代码

#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;
}