CF621E Wet Shark and Blocks
阿新 • • 發佈:2021-10-28
CF621E
行。
solution
一個 顯然的 \(dp\)
設 \(f_{i, j}\) 表示考慮了前 \(i\) 個格子,當前餘數為 \(j\) 的方案數。
轉移就列舉當前選的數
\[f_{i + 1, (j * 10 + v) \% x} += f_{i, j} \]然後你會發現轉移方程的每個 \(f_{i}\) 的轉移都是一樣的。
所以可以用矩陣加速轉移。
初始狀態:
\(f_0 = \{1, 0, 0, \dots 0\}\)
對於每個數 \(v\) 修改矩陣:
\(base[j][(j * 10 + v)\% x] += 1\)
最後答案就是 \(base^b \times f[0]\) 的第 \(k\)
code
#include<bits/stdc++.h> #define int long long using namespace std; const int MAXA = 1e4 + 5; const int MAXB = 1e5 + 5; const int MAXC = 1e6 + 5; const int mod = 1e9 + 7; int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0';c = getchar();} return x * f; } int n, b, k, x; struct Matrix{ int a[110][110]; Matrix() {memset(a, 0, sizeof a);} Matrix operator * (const Matrix &rhs)const{ Matrix ret; for (int i = 0; i < x; i++) for (int j = 0; j < x; j++) for (int k = 0; k < x; k++) ret.a[i][j] = (ret.a[i][j] + a[i][k] * rhs.a[k][j] % mod) % mod; return ret; } }base, Ans; Matrix pow(int k) { Matrix ret; for (int i = 0; i < x; i++) ret.a[i][i] = 1; while(k) { if(k & 1) ret = ret * base; k >>= 1; base = base * base; } return ret; } signed main() { n = read(), b = read(), k = read(), x = read(); for (int i = 1; i <= n; i++) { int val = read(); for (int j = 0; j < x; j++) base.a[j][(j * 10 % x + val % x) % x]++; } Ans = pow(b); cout<<Ans.a[0][k]; return 0; }