题目
题目链接:http://codeforces.com/contest/621/problem/E
题目来源:cf#341
简要题意:每位由一个数组中等概率选,求 b 为的数模
x 为 k 的方案数。
题解
首先统计每个数的个数,可以dp直接推,由于
b 很大,要矩阵快速幂来优化。1×x 的初始向量表示模 x 为几的方案数。
然后转移的矩阵
transi,j 即模 x 为i 的数后面跟一个数变为模 x 为j 的方案数。转移的矩阵 Θ(n2) 处理下即可。
利用模板可以快速AC,现场二十分钟左右过的,还好我接触矩阵快速幂比较多,不然得跪啊。
代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <set>
#include <map>
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define sz(x) ((int)(x).size())
#define fi first
#define se second
using namespace std;
typedef long long LL;
typedef vector<int> VI;
typedef pair<int,int> PII;
LL powmod(LL a,LL b, LL MOD) {LL res=1;a%=MOD;for(;b;b>>=1){if(b&1)res=res*a%MOD;a=a*a%MOD;}return res;}
// head
const int N = 105;
const LL MOD = 1e9+7;
struct Matrix {
LL grid[N][N];
int row, col;
Matrix() {
row = col = N;
memset(grid, 0, sizeof(grid));
}
Matrix operator *(const Matrix &b) {
Matrix res;
res.setSize(row, b.col);
for (int i = 0; i < res.row; i++) {
for (int j = 0; j < res.col; j++) {
LL t = 0;
for (int k = 0; k < col; k++) t += (grid[i][k] * b.grid[k][j]) % MOD;
res.grid[i][j] = t % MOD;
}
}
return res;
}
Matrix operator ^(int exp) {
Matrix res, temp;
res.setIdentity();
temp = *this;
for (; exp > 0; exp >>= 1, temp=temp*temp) {
if (exp & 1) res = temp * res;
}
return res;
}
void setSize(int row, int col) {
this->row = row, this->col = col;
}
void setValue(int row, int col, LL val) {
grid[row][col] = val;
}
LL getValue(int row, int col) {
return grid[row][col];
}
void clear() {
memset(grid, 0, sizeof(grid));
}
void setIdentity() {
clear();
for (int i = 0; i < N; i++) grid[i][i] = 1;
}
};
int main() {
int n, b, k, x, in;
scanf("%d%d%d%d", &n, &b, &k, &x);
Matrix init;
init.setSize(1, x);
for (int i = 0; i < n; i++) {
scanf("%d", &in);
init.grid[0][in%x]++;
}
Matrix trans;
trans.setSize(x, x);
for (int i = 0; i < x; i++) {
for (int j = 0; j < x; j++) {
int temp = (10*i+j)%x;
trans.grid[i][temp] += init.getValue(0, j);
}
}
init = (init)*(trans^(b-1));
printf("%I64d\n", init.getValue(0, k));
return 0;
}