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