Loading

CF621E Wet Shark and Blocks

题面

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;
}
posted @ 2021-10-28 09:53  Dita  阅读(38)  评论(0编辑  收藏  举报