[ABC235G] Gardens

发布时间 2023-10-16 15:38:18作者: taozhiming

[ABC235G] Gardens

题目描述:

有三种不同颜色的球,分别有 \(A,B,C\) 个。(相同颜色的球之间不区分)

将球放入 \(N\) 个不同的盒子中,要求:

  • 每个盒子至少放了一个球

  • 每个盒子不能存在两个相同颜色的球

  • 可以不放完所有的球

求放置方案数对 \(998244353\) 取模的结果。

对于 \(100\%\) 的数据,保证:$ 1\le N\le 5\times 10^6 $,\(0\le A,B,C\le N\)

题目分析:

考虑如果没有第一个限制,那么答案就是:

\[\sum_{i=0}^{A}\binom{n}{i}\times \sum_{i=0}^{B}\binom{n}{i} \times \sum_{i=0}^{C}\binom{n}{i} \]

考虑加上第第一个限制怎么做,我们设 \(g(i)\) 表示 \(i\) 个位置不受限制的方案数,\(f(i)\) 表示 \(i\) 个位置每个位置上至少有一个球的方案数,则:

\[g(n)=\sum_{i=0}^{n}\binom{n}{i}f(i) \\ g(n)=\sum_{i=0}^{A}\binom{n}{i}\times \sum_{i=0}^{B}\binom{n}{i} \times \sum_{i=0}^{C}\binom{n}{i} \]

可以二项式反演一下得到:

\[f(n)=\sum_{i=0}^{n}(-1)^{n-i}\binom{n}{i}g(i) \]

那么现在问题变成怎么快速求得 \(g(i)\),设 \(h(i)=\sum_{i=0}^{A}\binom{n}{i}\),因为 \(\binom{n}{m}=\binom{n-1}{m}+\binom{n-1}{m-1}\),所以:

\[h(i+1)=\sum_{j=0}^{A}\binom{i+1}{j}=\sum_{j=0}^{A}\binom{i}{j}+\sum_{j=0}^{A}\binom{i}{j-1}=\sum_{j=0}^{A}\binom{i}{j}+\sum_{j=1}^{A+1}\binom{i}{j-1}-\binom{i}{A}=2\times h(i)-\binom{i}{A} \]

可以递推预处理得到,复杂度线性。

代码:

const int INF=1e9+7;
const int N=6e6+7;
const int mod=998244353;

int f[N],g[N],h[N];
int fac[N],ifac[N];
int n,A,B,C;

int qmi(int a,int k){
  int res=1;
  while(k){
      if (k&1) res=res*a%mod;
      a=a*a%mod;k>>=1;
  }return res;
}

int binom(int n,int m)
{
  if (n<m||n<0||m<0) return 0;
  return fac[n]*ifac[m]%mod*ifac[n-m]%mod;
}

signed main(){
  scanf("%lld%lld%lld%lld",&n,&A,&B,&C);
  fac[0]=1;int inv2=qmi(2,mod-2);
  for (int i=1;i<=n;i++) fac[i]=fac[i-1]*i%mod;
  ifac[n]=qmi(fac[n],mod-2);
  for (int i=n-1;i>=0;i--) ifac[i]=ifac[i+1]*(i+1)%mod;
  for (int i=0;i<=A;i++) f[n]=(f[n]+binom(n,i))%mod;
  for (int i=n-1;i>=0;i--) f[i]=(f[i+1]+binom(i,A))%mod*inv2%mod;
  for (int i=0;i<=B;i++) g[n]=(g[n]+binom(n,i))%mod;
  for (int i=n-1;i>=0;i--) g[i]=(g[i+1]+binom(i,B))%mod*inv2%mod;
  for (int i=0;i<=C;i++) h[n]=(h[n]+binom(n,i))%mod;
  for (int i=n-1;i>=0;i--) h[i]=(h[i+1]+binom(i,C))%mod*inv2%mod;
  int ans=0;
  for (int i=0;i<=n;i++)
      ans=(ans+(((n-i)&1)?mod-1:1)*binom(n,i)%mod*f[i]%mod*g[i]%mod*h[i]%mod)%mod;
  printf("%lld\n",ans);
  return 0;
}