codeforces 621E(dp, matrices)
2016-02-01 14:50
351 查看
题目大意:
输入4个数字, n, b, k, x;
有b数量的的 “包裹”, 每个”包裹“中含有相同的n个数字, 数字a的取值为 0 < a < 10; 从b数量的”包裹“中取出这些数字组成一个数字num; 比如 有 3个”包裹“, 从左到右依次取出1, 2, 3; 则组成一个3位数 123; 现在让你求有多少个方案满足num % x== k ; 因为方案数可能很多,最后的结果取余1e9+7;
题目分析:
First, let us build an X by X matrix. We will be applying matrix exponentiation on this matrix. For each modulo value T from 0
to X — 1, and each value in the array with index i between 1 and n, we will do: matrix[T][(10 * T + arr[i]) % X]++. This is because, notice that for each block we allow one more way to go between a modulo value T, and (10 * T + arr[i]) % X. We are multiplying
T by 10 because we are "left-shifting" the number in a way (i.e. changing 123 -> 1230), and then adding arr[i] to it. Notice that this basically simulates the concatenation that Wet Shark is conducting, without need of a brute force dp approach.
这是官方题解,我大致翻译一下:
建立一个x * x的矩阵 matrix, 我们将使用矩求幂的方法完成(矩阵快速幂), 对于每一个取余x后的值T,取值范围( 0 < T < x-1 ), 然后对于我们输入的数字(block中的n个值),我们将进行: matrix[T][(10*T+arr[i])%x]++;
这样做的原因是, 表示从T 到达 (10*T+arr[i])%x 的方案数, 建议参考代码; (10*T+arr[i])%x 是模拟两个数字的结合(因为题目要求取余结果,根据取余原则,%x即可);
输入4个数字, n, b, k, x;
有b数量的的 “包裹”, 每个”包裹“中含有相同的n个数字, 数字a的取值为 0 < a < 10; 从b数量的”包裹“中取出这些数字组成一个数字num; 比如 有 3个”包裹“, 从左到右依次取出1, 2, 3; 则组成一个3位数 123; 现在让你求有多少个方案满足num % x== k ; 因为方案数可能很多,最后的结果取余1e9+7;
题目分析:
First, let us build an X by X matrix. We will be applying matrix exponentiation on this matrix. For each modulo value T from 0
to X — 1, and each value in the array with index i between 1 and n, we will do: matrix[T][(10 * T + arr[i]) % X]++. This is because, notice that for each block we allow one more way to go between a modulo value T, and (10 * T + arr[i]) % X. We are multiplying
T by 10 because we are "left-shifting" the number in a way (i.e. changing 123 -> 1230), and then adding arr[i] to it. Notice that this basically simulates the concatenation that Wet Shark is conducting, without need of a brute force dp approach.
这是官方题解,我大致翻译一下:
建立一个x * x的矩阵 matrix, 我们将使用矩求幂的方法完成(矩阵快速幂), 对于每一个取余x后的值T,取值范围( 0 < T < x-1 ), 然后对于我们输入的数字(block中的n个值),我们将进行: matrix[T][(10*T+arr[i])%x]++;
这样做的原因是, 表示从T 到达 (10*T+arr[i])%x 的方案数, 建议参考代码; (10*T+arr[i])%x 是模拟两个数字的结合(因为题目要求取余结果,根据取余原则,%x即可);
#include <bits/stdc++.h> using namespace std; const int mod = 1e9+7; const int maxn = 100+5; int matrix[maxn][maxn], s[maxn][maxn]; int n, b, k, x; int cnt[10], tmp[maxn][maxn]; void mul(int a[][maxn], int b[][maxn]){ for(int i = 0; i < x; ++i){ for(int j = 0; j < x; ++j){ int t(0); for(int k = 0; k < x; ++k){ t = (t+1LL*a[i][k]*b[k][j])%mod; } tmp[i][j] = t; } } for(int i = 0; i < x; ++i) for(int j = 0; j < x; ++j) a[i][j] = tmp[i][j]; } int main() { while(~scanf("%d%d%d%d", &n, &b, &k, &x)){ for(int i = 0; i < n; ++i){ int x; scanf("%d", &x); cnt[x]++; } for(int i = 0; i < x; ++i) for(int j = 0; j < 10; ++j){ matrix[i][(i*10+j)%x] += cnt[j]; } for(int i = 0; i < x; ++i) s[i][i] = 1; while(b){ if(b&1) mul(s, matrix); mul(matrix, matrix); b /= 2; } printf("%d\n", s[0][k]); } }
相关文章推荐
- 制作winform安装程序
- 抓取crash
- 查看python的admin模板位置
- nginx笔记
- OpenCV 图像相似度匹配之感知哈希算法
- MySQL 触发器简单实例
- logstash日志分析的配置和使用
- 封装好的socket,拿去用
- Ubuntu下Redis的学习(一)
- 一道简单的题目引发的思考
- 消息队列技术终结者(一)—通俗深刻地认识JMS(即Java Message Service)
- win7 64位上Oracle11g数据库的安装,卸载,plsql的安装
- 使用HttpURLConnection发送HTTP请求
- 使用clippath时在有些系统版本上无效
- Spring使用Ehcache
- SpringMVC4.2+Jackson2.6/2.7
- while和if的区别
- 每天一点正能量 - 幸福需要一点点的积累
- tomcat笔记
- 解决jmeter线程组循环次数无效