「acmhdu - 6314」Matrix


link。

首先将问题弱化为 1-d,我们待定容斥系数 \(f_i\),可以写出答案的式子:\(\sum\limits_{i=a}^nf_i\binom{n}{i}2^{n-i}\)。解释就是,我们想让 \(\binom{n}{i}2^{n-i}\) 达到“至少”的效果,但是明显会算重,所以通过这个容斥系数 \(f_i\) 达到“恰好”的效果,于是原题“至少”的答案就是这个。

每一个“恰好” \(i\) 个的方案数在最终的答案中的贡献次数为 \(1\),也就是说 \(\sum\limits_{j=a}^if_j\binom{i}{j}=1\)。这个的意思就是如果至少有 \(i\) 的方案数重了,那么它一定是从前面开始重的(就是说 \(1,\dots,i-1\) 的随便摆的部分跟它重了),所以从前面开始容斥。

然后就好算了,可以直接得出 \(f_i=\sum\limits_{j=a}^{i-1}f_j\binom{i-1}{j-1}\),或者你也可以用下吸收公式推式子。

但实际上这个题还有一些常数的优化,具体可以看看 Siyuan 的博客。

#include
#define il __inline__ __attribute__((always_inline))
constexpr int kMod=998244353;
__int128 sum;
int n,m,A,B,i,j,k;
int coef[2][3100],pw[9000100],bin[3100][3100];
il void MCase() {
  for(k=0; k<2; ++k) {
    coef[k][0]=1;
    for(int i=(k?B:A); i<=(k?m:n); ++i) coef[k][i]=1ll*(((i-(k?B:A))&1)?-1:1)*bin[i-1][(k?B:A)-1]%kMod*bin[k?m:n][i]%kMod;
  }
  int res=0;
  for(i=A; i<=n; ++i)
    for(j=B; j<=m; ++j) (res+=1ll*coef[0][i]*coef[1][j]%kMod*pw[(n-i)*(m-j)]%kMod)%=kMod;
  std::printf("%d\n",res<0?res+kMod:res);
}
signed main(int argc,char const* argv[]) {
  pw[0]=1;
  for(i=1; i<9000100; ++i) pw[i]=1ll*pw[i-1]*2%kMod;
  bin[0][0]=1;
  for(i=1; i<3100; ++i) {
    bin[i][0]=1;
    for(j=1; j<=i; ++j) bin[i][j]=(bin[i-1][j]+bin[i-1][j-1])%kMod;
  }
  for(; ~std::scanf("%d%d%d%d",&n,&m,&A,&B);) MCase();
  return 0;
}