CF621E Wet Shark and Blocks

题意

出门右转http://codeforces.com/problemset/problem/621/E

题解

首先,一个dp应该是显然的。

\(dp[i][j]\) 表示选到第 \(i\) 个格子,余数是 \(j\) 的方案数,枚举取数 \(l\),得到

\[dp[i+1][(10j+a_{l})\bmod x]\text{ += }dp[i][j]\]

可以发现对于每一个 \(dp[i]\),转移都是类似的。

然后我们考虑用矩阵快速幂优化转移。

初始状态 \(dp[0]\)
\[\begin{bmatrix}1\\0\\\vdots\\0\end{bmatrix}\]

然后对于每个数 \(v\),我们修改转移矩阵\(A\)
\[A\left[j\right]\left[\left(10j+v\right)\bmod x\right]\text{ += }1\]
然后最终答案就是 \(A^b\times dp[0]\) 的第 \(k\) 行了。

调试记录

  • 转移矩阵错了QaQ

代码

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
ll n, b, k, x;
const ll P = 1000000007;
struct Matrix {
    ll a[105][105];
};

Matrix A, I;

inline ll read() {
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
inline Matrix MatrixMul(const Matrix &A, const Matrix &B) {
    Matrix ret;
    for (int i=0; i<x; i++)
        for (int j=0; j<x; j++) {
            ret.a[i][j] = 0;
            for (int k=0; k<x; k++)
                (ret.a[i][j] += A.a[i][k] * B.a[k][j] % P) %= P;
        }
    return ret;
}
inline Matrix Pow(ll k){
    Matrix ans = I;
    for (; k; k>>=1, A=MatrixMul(A, A)) if (k&1) ans = MatrixMul(ans, A);
    return ans; 
}

int main() {
    n = read(); b = read(); k = read(); x = read();
    for (int i=0; i<x; i++) I.a[i][i] = 1;
    for (int i=0; i<n; i++) {
        ll val = read();
        for (int j=0; j<x; j++)
            ++A.a[j][(j*10%x+val%x)%x];
    }
    Matrix ret = Pow(b);
    cout << ret.a[0][k] << endl;
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/mchmch/p/codeforces-621E.html