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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM