BestCoder Round #62 (div.2) HDOJ5564 Clarke and digits(dp + 快速幂)

32 篇文章 0 订阅
29 篇文章 0 订阅

Clarke and digits

Time Limit: 5000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 88    Accepted Submission(s): 44


Problem Description
Clarke is a patient with multiple personality disorder. One day, Clarke turned into a researcher, did a research on digits. 
He wants to know the number of positive integers which have a length in  [l,r]  and are divisible by  7  and the sum of any adjacent digits can not be  k .
 

Input
The first line contains an integer  T(1T5) , the number of the test cases. 
Each test case contains three integers  l,r,k(1lr109,0k18) .
 

Output
Each test case print a line with a number, the answer modulo  109+7 .
 

Sample Input
  
  
2 1 2 5 2 3 5
 

Sample Output
  
  
13 125 Hint: At the first sample there are 13 number $7,21,28,35,42,49,56,63,70,77,84,91,98$ satisfied.
 



题目链接:点击打开链接

dp[i][j]表示长度为i取模为7的种类数, 参考数据范围, 直接计算会TLE, 用矩阵快速幂来加速运算, 第一次做矩阵快速幂的题目, 参考了题

解, 1LL防止数据溢出出错, 转态转移方程: z.dp[i][j] = (z.dp[i][j] + 1LL * a.dp[i][k] * b.dp[k][j] % MOD) % MOD

AC代码:

#include "iostream"
#include "cstdio"
#include "cstring"
#include "algorithm"
#include "cmath"
#include "utility"
#include "map"
#include "set"
#include "vector"
using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 100;
struct Matrix
{
	/* data */
	int row, col, dp[MAXN][MAXN];
	void init(int r, int c) {
		row = r;
		col = c;
		memset(dp, 0, sizeof(dp));
	}
}x, y, z;
int l, r, k;
void magic(int k)
{
	for(int i = 1; i < 10; ++i)
		x.dp[i * 7 + i % 7][0]++;
	for(int i = 0; i < 10; ++i)
		for(int j = 0; j < 7; ++j) {
			int u = i * 7 + j;
			for(int m = 0; m < 10; ++m) 
				if(i + m != k) {
					int v = m * 7 + (j * 10 + m) % 7;
					y.dp[v][u]++;
			}
		}
	for(int i = 0; i <= 10; ++i)
		y.dp[70][i * 7] = 1;
}
void mul(const Matrix &a, const Matrix &b, Matrix &c)
{
	z.init(a.row, b.col);
	for(int i = 0; i < z.row; ++i)
		for(int j = 0; j < z.col; ++j)
			for(int k = 0; k < a.col; ++k)
				z.dp[i][j] = (z.dp[i][j] + 1LL * a.dp[i][k] * b.dp[k][j] % MOD) % MOD;
	c = z;
}
int power_mod(Matrix a, Matrix b, int n)
{
	while(n > 0) {
		if(n & 1) mul(b, a, a);
		mul(b, b, b);
		n >>= 1;
	}
	return a.dp[70][0];
}
int main(int argc, char const *argv[])
{
	int t;
	scanf("%d", &t);
	while(t--) {
		x.init(MAXN, 1);
		y.init(MAXN, MAXN);
		scanf("%d%d%d",&l, &r, &k);
		magic(k);
		int ans = (power_mod(x, y, r) - power_mod(x, y, l - 1) + MOD) % MOD;
		printf("%d\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值