Clarke and digits

 Accepts: 16
 Submissions: 29
 Time Limit: 5000/3000 MS (Java/Others)
 Memory Limit: 65536/65536 K (Java/Others)
问题描述
克拉克是一名人格分裂患者。某一天,克拉克变成了一个研究人员,在研究数字。
他想知道在所有长度在[l, r][l,r]之间的能被77整除且相邻数位之和不为kk的正整数有多少个。
输入描述
第一行一个整数T(1 \le T \le 5)T(1≤T≤5),表示数据的组数。
每组数据只有一行三个整数l, r, k(1 \le l \le r \le 10^9, 0 \le k \le 18)l,r,k(1≤l≤r≤10​9​​,0≤k≤18)。
输出描述
每组数据输出一行一个数,表示答案。由于答案太大,你只需对10^9+710​9​​+7取模即可。  
输入样例
2
1 2 5
2 3 5
输出样例
13
125
Hint
第一个样例有13个数满足,分别是:7,21,28,35,42,49,56,63,70,77,84,91,987,21,28,35,42,49,56,63,70,77,84,91,98

这个题目看着题解想了一天,收获特别多多多多。

一开始刚看这个题目的时候想法是dp, dp[i][j][k]表示长度为i,最后一位为j,余数为k的个数。

然后转移方程就是 dp[i+1][x][(j*10+x)%7] += dp[i][j][k] (x从0到9)。这样不行因为R太大,每次求一定TLE。我当前的水平就想到这里了。。。

然后就是学习了。。。

学习点之一:发现当前最后一位j与当前的余数k,其状态数就70个。有趣的是,其状态转移是确定的,即是一个70*70的矩阵,这样我们对长度为X的数,我们先求长度为1的矩阵A,再将A*转移方程B^(X-1)。然后就是矩阵中的[0][0^9]的和。(表示余数为0,末尾数字是0~9)。然后矩阵的多少次方就可以用快速幂来求。

学习点之二:注意这样求的是长度为X的数。我们现在想求的是长度为1到长度为X的数,这样对于[L,R]来说,直接相减就好了。所以就想求A、A*B、A*B^2、A*B^3、。。。这样的前缀和。

之前求矩阵的前缀和求过这样的B、B^2、B^3、B^4。。。。可以用分治法来求。

但这样的我就不知道怎么搞了。

结果题解上是加了一列matrix[0^9][70]=1,并且matrix[70][70]=1。

这样当我们求A*(B^R)的时候,res.matrix[0][70]表示的就是前缀和矩阵的所有和。这块做法太亮了,太亮了。之前没有玩过这种方法。

附加学习点之三:friend Matrix operator ^(Matrix A, int n);这块调用了A矩阵,其值发生了变化,每一个test需要重置一下B矩阵。

最后想通的感觉特别痛快。

代码:

#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <string>
#include <cstring>
#pragma warning(disable:4996)
using namespace std; const int maxn = 71;
const int mod = 1e9 + 7; struct Matrix
{
int mat[maxn][maxn];
Matrix()
{
memset(mat, 0, sizeof(mat));
}
void clear(){ memset(mat, 0, sizeof(mat)); }
friend Matrix operator *(const Matrix &A, const Matrix &B);
friend Matrix operator ^(Matrix A, int n);
}; Matrix res1, res2; Matrix operator *(const Matrix &A, const Matrix &B)
{
Matrix ret;
for (int i = 0; i < maxn; i++)
{
for (int j = 0; j < maxn; j++)
{
for (int k = 0; k < maxn; k++)
{
ret.mat[i][j] = (ret.mat[i][j] + (1LL*A.mat[i][k] * B.mat[k][j]) % mod) % mod;
}
}
}
return ret;
} Matrix operator ^(Matrix A, int n)
{
Matrix ret;
for (int i = 0; i < maxn; i++)
{
ret.mat[i][i] = 1;
}
for (; n; n >>= 1, A = A*A)
if (n & 1)
ret = ret*A;
return ret;
} inline int statu(int i, int j)
{
return i * 10 + j;
} int main()
{
//freopen("i.txt","r",stdin);
//freopen("o.txt","w",stdout); int t;
int i, j, L, R, K, x; Matrix A, B;
for (i = 1; i < 10; i++)
A.mat[0][statu(i % 7, i)] = 1; scanf("%d", &t);
while (t--)
{
scanf("%d%d%d", &L, &R, &K); B.clear();
for (i = 0; i < 7; i++)
{
for (j = 0; j < 10; j++)
{
for (x = 0; x < 10; x++)
{
if (j + x != K)
{
B.mat[statu(i, j)][statu((i * 10 + x) % 7, x)] = 1;
}
}
}
} for (i = 0; i < 10; i++)
B.mat[i][maxn - 1] = 1;
B.mat[maxn - 1][maxn - 1] = 1; res1 = A*(B^R);
res2 = A * (B ^ (L - 1));
printf("%d\n", (res1.mat[0][maxn - 1] - res2.mat[0][maxn - 1] + mod) % mod);
}
//system("pause");
return 0;
}

HDU 5564:Clarke and digits 收获颇多的矩阵快速幂 + 前缀和的更多相关文章

  1. hdu 2243 考研路茫茫——单词情结 ac自动机+矩阵快速幂

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=2243 题意:给定N(1<= N < 6)个长度不超过5的词根,问长度不超过L(L <23 ...

  2. HDU 2157 How many ways??(简单线性DP | | 矩阵快速幂)

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=2157 这道题目很多人的题解都是矩阵快速幂写的,矩阵快速幂倒是麻烦了许多了.先给DP的方法 dp[i][ ...

  3. hdu 5564 Clarke and digits 矩阵快速幂优化数位dp

    Clarke and digits Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others ...

  4. HDU 5564 Clarke and digits 状压dp+矩阵加速

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在[L,R]范围,并且能整除7的整数的总数. 题解: 考虑最原始的想法: dp[ ...

  5. hdu 5564 Clarke and digits

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=5564 ------------------------------------------------ ...

  6. HDU 4549 M斐波那契数列(矩阵快速幂)

    题目链接:M斐波那契数列 题意:$F[0]=a,F[1]=b,F[n]=F[n-1]*F[n-2]$.给定$a,b,n$,求$F[n]$. 题解:暴力打表后发现$ F[n]=a^{fib(n-1)} ...

  7. HDU 4549 M斐波那契数列(矩阵快速幂+费马小定理)

    M斐波那契数列 Time Limit : 3000/1000ms (Java/Other)   Memory Limit : 65535/32768K (Java/Other) Total Submi ...

  8. HDU 5015 233 Matrix(网络赛1009) 矩阵快速幂

    先贴四份矩阵快速幂的模板:http://www.cnblogs.com/shangyu/p/3620803.html http://www.cppblog.com/acronix/archive/20 ...

  9. hdu 5171 GTY's birthday gift(数学,矩阵快速幂)

    题意: 开始时集合中有n个数. 现在要进行k次操作. 每次操作:从集合中挑最大的两个数a,b进行相加,得到的数添加进集合中. 以此反复k次. 问最后集合中所有数的和是多少. (2≤n≤100000,1 ...

随机推荐

  1. Docker配置阿里云镜像源

    Docker默认拉取镜像是从这里拉取(https://hub.docker.com/),拉取的速度让人...,所以是配置国内镜像源,拉取速度十分惊人 一.版本要求 Docker版本:1.10以上 二. ...

  2. GO学习之 为什么选择GO

    一.Go语言为并发而生 如上所述,硬件制造商正在为处理器添加越来越多的内核以提高性能.所有数据中心都在这些处理器上运行,更重要的是,今天的应用程序使用多个微服务来维护数据库连接,消息队列和维护缓存.因 ...

  3. Java的Path、Paths和Files

    前言 因为这几天被java.nio的这几个接口和工具类卡到了,就顺便地查了一波文档以及使用方法,这篇其实更像是API的复制粘贴,只不过我在注释里多写了一些output和注意事项,看不惯API的可以选择 ...

  4. 一篇文章带你了解JavaScript中的变量,作用域和内存问题

    1 在JavaScript中的变量分别区分为两种: 一种为基本类型值,一种为应用类型值. 基本类型值指的是简单的数据段 引用类型值为可能由多个值组成的对象 引用类型的值是保存在内存中的对象,JavaS ...

  5. js 一句代码 让网页变为编辑器

    document.body.contentEditable = true 只要在控制台执行这行语句   页面就可以自由输入编辑了

  6. Spring基础篇——通过Java注解和XML配置装配bean(转载)

      作者:陈本布衣 出处:http://www.cnblogs.com/chenbenbuyi 本文版权归作者和博客园共有,欢迎转载分享,但必须保留此段声明,且在文章页面明显位置给出原文链接,否则保留 ...

  7. Spring扫描组件的使用详解

    https://blog.csdn.net/you18131371836/article/details/53691044?utm_source=blogxgwz5

  8. Windows 搭建WAMP+Mantis

    下载WAMP http://www.wampserver.com/ 安装直接下一步就行 安装完启动后,显示下面的logo 在浏览器输入 127.0.0.1/phpmyadmin    设置数据库(默认 ...

  9. sql注入小姿势

    利用/*!union*/可以绕过对union的过滤

  10. 吴裕雄 python 神经网络——TensorFlow 数据集基本使用方法

    import tempfile import tensorflow as tf input_data = [1, 2, 3, 5, 8] dataset = tf.data.Dataset.from_ ...