cf621 E. Wet Shark and Blocks
题意:
长为 n 的数组,元素都是 \(1\sim 9\) 的整数。每次从数组中有放回地取数,取 b 次,把取出来的数组成一个大整数。问使得这个大整数 \(\%x=k\) 的方案数。
\(1\le a_i\le 9,2\le n\le 5e4, 1\le b\le 1e9,0\le k
思路:
\(dp(i,j)\) 表示取了 \(i\) 位数,凑出来的和模 x 为 \(j\) 的方案数。则 \(dp(i+1,(10j+a_{1\sim n})\%x)+=dp(i,j)\)
矩阵快速幂优化,行向量的第 \(j\) 个元素 \(B(j)\) 表示凑出 \(j\) 的方案数,\(0\le j < x\)
\[\begin{pmatrix} B_0 & B_1 & \cdots & B_{x-1} \end{pmatrix} \begin{pmatrix} \cdots & A_{0,j} & \cdots \\ \cdots & A_{1,j} & \cdots \\ & \vdots & \\ \cdots & A_{x-1,j} & \cdots \end{pmatrix} = \begin{pmatrix} \cdots & B'_{j} & \cdots \end{pmatrix} \]怎么构造 \(A\) 呢?要让新的 \(B_j' = \sum\limits _{ (10i+v)\%x=j } B_i\),只需对数组中的每个数 \(v\),把 \(A[i][j=(10i+v)\%x]\) 加上1
注意到一开始 \(B=(1,0,0,\cdots)\),所以答案是 \(A[0][k]\)
cin >> n >> b >> k >> x;
for(int i = 1; i <= n; i++) {
ll v; cin >> v;
for(int j = 0; j < x; j++)
++A[j][(j*10+v)%x];
}
qmi(A, b);
cout << A[0][k];