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

posted @ 2018-08-14 15:22  MCH__ds  阅读(1391)  评论(0编辑  收藏  举报