题意:求

$$
\sum_{i=1}^{ik+r\le n}{\text{C}^{ik+r}_{nk}}\left( \text{mod\;}p \right)
$$

观察后发现实际上是求 $\mod p = r$ 的组合数之和

$dp[i][j]$表示从 $i$ 个球中取 $j$ 个的方案数 其中$j$ 满足 $j \equiv r \pmod k$

所以$dp[i][j] = dp[i-1][j-1 \pmod k] + dp[i-1][j]$

可以用矩阵乘法来优化

struct Matrix {
  int mat[51][53], x, y;
  inline void init(int n, int m) {
    x = n, y = m;
    lop(i, 1, x) lop(j, 1, y) mat[i][j] = 0;
  }
  inline Matrix &operator *(const Matrix &rhs) const {
    assert(x && y && rhs.x && y == rhs.x);
    static Matrix ret; ret.init(x, rhs.y);
    lop(i, 1, x)
      lop(k, 1, y) if (mat[i][k])
        lop(j, 1, rhs.y) {
          ret.mat[i][j] += mat[i][k] * 1ll * rhs.mat[k][j] % mod;
          if (ret.mat[i][j] >= mod) ret.mat[i][j] -= mod;
        } 
    return ret;
  }
  inline void operator ^=(ll k) {
    static Matrix ret; ret.init(x, y);
    lop(i, 1, x) ret.mat[i][i] = 1;
    while (k) {
      if (k & 1) ret = ret * (*this);
      *this = *this * (*this);
      k >>= 1;
    }
    *this = ret;
  }
} a, b;

int main() {
  cin >> n >> mod >> k >> r;
  a.init(1, k);
  a.mat[1][1] = 1;
  b.init(k, k);
  lop(i,0,k-1) ++b.mat[i+1][i+1], ++b.mat[i+1][(i-1+k)%k+1];//if your code is b.mat[...][...] = 1, when k = 1, it will be wrong (you can see pascal's trangle 2 = 1 + 1 but not 2 = 1 + 0)
  b ^= 1ll * n * k;
  a = a * b;
  cout << a.mat[1][r+1];
  return 0;
}




发表评论

电子邮件地址不会被公开。 必填项已用*标注