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

原创 2015年11月19日 23:40:36

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(1T5),表示数据的组数。  
每组数据只有一行三个整数l, r, k(1 \le l \le r \le 10^9, 0 \le k \le 18)l,r,k(1lr109,0k18)
输出描述
每组数据输出一行一个数,表示答案。由于答案太大,你只需对10^9+7109+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 (dp+矩阵加速)

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 问题描述 克拉克是一名人格分裂患者。某一天,克拉克变成了一个研究人员,在研究数字。 ...
  • w20810
  • w20810
  • 2015年11月16日 13:20
  • 743

hdu 5564 Clarke and digits(矩阵快速幂)

题目链接:hdu 5564 Clarke and digits解题思路(i,j)表示该位为i并且取模7为j的种数。根据k构造一个70*70的矩阵代码#include #include #inclu...

hdu1270.小希的数表

http://acm.hdu.edu.cn/showproblem.php?pid=1270

hdu 1270 小希的数表

/* 枚举答案的第一个数。 可知 枚举的第一个数若是正确的。 那么用题目所给的输入数组 一个一个的减去第一个数得到一个数bi。用bi与前面的b1到bi-1分别相加。 如果都是hash记录的数 则bi就...

HDU 5950 Recursive sequence(构造矩阵+矩阵乘法)——2016ACM/ICPC亚洲区沈阳站(重现赛)

传送门 Recursive sequenceTime Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O...

51nod 1113 矩阵快速幂【裸题】【内含黑科技】

1113 矩阵快速幂 基准时间限制:3 秒 空间限制:131072 KB 分值: 40 难度:4级算法题 给出一个N * N的矩阵,其中的元素均为正整数。求这个...

hdu 5564 Clarke and digits

传送门: http://acm.hdu.edu.cn/showproblem.php?pid=5564 题意: 求长度在l到r之间,能被7整除,且相邻数位和不是k的数的个数?思路: 很明显的d...
  • yp_2013
  • yp_2013
  • 2016年01月28日 21:04
  • 257

hdu5564 Clarke and digits

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission...

hdu 5411 CRB and Puzzle(矩阵快速幂)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5411 解题思路: 题目大意: 给定n个点 常数m 下面n行第i行第一个数字表示i点的出...

hdu 5411 CRB and Puzzle 矩阵快速幂

题意:有n种数量无限的方块,每种方块后可以拼接另一个方块,但是只能拼接给定种类的方块,问最多拼接M次能拼接出多少种不同的样式。这道题中n只有50,很容易想到矩阵快速幂,毕竟这种题已经烂大街了。然而比赛...
  • CHCXCHC
  • CHCXCHC
  • 2015年08月26日 14:34
  • 290
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:HDU 5564:Clarke and digits 收获颇多的矩阵快速幂 + 前缀和
举报原因:
原因补充:

(最多只允许输入30个字)