1. 程式人生 > 其它 >CF621E Wet Shark and Blocks

CF621E Wet Shark and Blocks

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