题目背景

SOURCE:NOIP2015-GDZSJNZX(难)

题目描述

Mike 正在在忙碌地发着各种各样的的短信。旁边的同学 Tom 注意到,Mike 发出短信的接收方手机号码似乎都满足着特别的性质,难道Mike 的好朋友是满足正态分布的?Tom 很好奇。

由于 Mike 有着自己最喜欢的数字 a ,并且 a 的范围是:2≤a≤9 。Tom 从这里入手,发现了一些端倪,假设 Mike 发的电话号码是一个十进制数字 S ,Tom 发现 S 会满足以下三个性质中的一个:

1.S 是 a 的倍数。

2.S 在十进制表示下的各项数字加起来是 a 的倍数。

3.S 的某一位是 a 。

比如说当 a=7 时,21,16,17 这三个数字组成的电话号码都是会被Mike发短信的,他们分别满足 1,2,3 性质。

Tom 在想:如果给你两个自然数 L,R,以及 Mike 最喜欢的数字 a ,在 [L,R] 中有多少个号码是 Mike 要发短信的手机号码,只需要你告诉他这些数字的平方和。比如说 3,7 是合法的,那么你应该输出 32 + 72 = 58 这个数。

当然,由于答案可能很大,你只需要将答案对 10^9 + 7 取模即可。

输入格式

输入的第一行包括一个正整数 T ,表示总共有 T 组询问。

接下来有 T 行,每行三个整数 L,R,A 。

输出格式

输出包括 T 行,每行一个整数,表示对 10^9 + 7 取模的答案。

样例数据 1

输入

3

2 20 6

3 203 7

11 771 2

输出

1884

1593269

32817226

备注

【数据范围】

对于 15% 的数据,0≤L≤R≤10^6,T=1

对于 35% 的数据,0≤L≤R≤10^7,T=1

另外有 25% 的数据,A=2;L=10k;R=10v;k和v都是自然数。

对于 100% 的数据,0≤L≤R≤10^18;2≤A≤9;T≤100

先看一眼题面,再看一眼数据范围不难想到这题想考数位dp

但常规的数位dp只要求求出满足条件的数的个数,该题要求的是这些数的平方和,为了解决这个问题,我们可以先考虑这个问题的弱化版本:如何求出这些数的和?

我们可以将普通数位dp要求的数的数量抽象成0维上的问题,那么该题就是要求二维问题,显然我们可以用0维的状态推出1维的状态,那么自然我们也可以用0维和1维的状态来推出二维的状态。那么我们可以利用完全平方式来推出答案,设前几位的值为a,当前位的值为b,那么,合并起来的值是(10a+b),那么合并起来的值的平方为100a2+20ab+b2,由于a和b都知道,那么就做完了。

注:状态转移方程有点恶心、

代码:

#include<bits/stdc++.h>
#define ll long long
#define mod 1000000007
using namespace std;
ll t,m,l,r,dp[3][20][10][10][2][2],num[20];
// ^ 每一位的和 数的大小 是否出现过 是否满位
inline ll sol(ll x){
	if(x==-1||x==0)return 0;
	ll ans=0,len=0;
	while(x)num[++len]=x%10,x/=10;
	for(int i=1;i<=(len>>1);++i)swap(num[i],num[len-i+1]);
	memset(dp,0,sizeof(dp));
	for(int i=0;i<num[1];++i){
		dp[0][1][i%m][i%m][i==m][0]+=1;
		dp[1][1][i%m][i%m][i==m][0]+=i;
		dp[2][1][i%m][i%m][i==m][0]+=i*i;
	}
	dp[0][1][num[1]%m][num[1]%m][num[1]==m][1]+=1;
	dp[1][1][num[1]%m][num[1]%m][num[1]==m][1]+=num[1];
	dp[2][1][num[1]%m][num[1]%m][num[1]==m][1]+=num[1]*num[1];
	for(int i=1;i<len;++i)
	for(int j=0;j<m;++j)
	for(int k=0;k<m;++k)
	for(int t=0;t<2;++t){
		for(int s=0;s<=9;++s){
			dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+dp[0][i][j][k][t][0])%mod;
			dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+10LL*dp[1][i][j][k][t][0]+1LL*s*dp[0][i][j][k][t][0])%mod;
			dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+100LL*dp[2][i][j][k][t][0]+20LL*s*dp[1][i][j][k][t][0]+1LL*s*s*dp[0][i][j][k][t][0])%mod;
		}
		for(int s=0;s<num[i+1];++s){
			dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+dp[0][i][j][k][t][1])%mod;
			dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+10LL*dp[1][i][j][k][t][1]+1LL*s*dp[0][i][j][k][t][1])%mod;
			dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]=(dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][0]+100LL*dp[2][i][j][k][t][1]+20LL*s*dp[1][i][j][k][t][1]+1LL*s*s*dp[0][i][j][k][t][1])%mod;
		}
		int s=num[i+1];
		dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]=(dp[0][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]+dp[0][i][j][k][t][1])%mod;
		dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]=(dp[1][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]+10LL*dp[1][i][j][k][t][1]+1LL*s*dp[0][i][j][k][t][1])%mod;
		dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]=(dp[2][i+1][(j+s)%m][(k*10+s)%m][(s==m)||t][1]+100LL*dp[2][i][j][k][t][1]+20LL*s*dp[1][i][j][k][t][1]+1LL*s*s*dp[0][i][j][k][t][1])%mod;
	}
	for(int i=0;i<m;++i)
	for(int j=0;j<m;++j)
	for(int k=0;k<=1;++k)
	ans=(ans+dp[2][len][i][j][1][k])%mod;
	for(int i=0;i<m;++i)
	for(int j=0;j<=1;++j)
	ans=(ans+dp[2][len][0][i][0][j])%mod;
	for(int i=1;i<m;++i)
	for(int j=0;j<=1;++j)
	ans=(ans+dp[2][len][i][0][0][j])%mod;
	return ans;
}
int main(){
	scanf("%lld",&t);
	while(t--){
		scanf("%lld%lld%lld",&l,&r,&m);
		printf("%lld\n",(sol(r)-sol(l-1)+mod)%mod);
	}
	return 0;
}

2018.06.26 NOIP模拟 号码(数位dp)的更多相关文章

  1. 2018.10.26 NOIP模拟 瓶子 (dp/贪心)

    传送门 正解是dp并不想去想了. 自己yy了一个贪心拿了95pts95pts95pts,唯一没过的点还只有一个地方错了,面向数据变成之后过啦! 所以我讲讲如何贪心. 考虑到最后都只会合并成一种颜色,所 ...

  2. 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)

    题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...

  3. 2018.06.29 NOIP模拟 边的处理(分治+dp)

    边的处理(side.cpp) [问题描述] 有一个 n 个点的无向图,给出 m 条边,每条边的信息形如<x,y,c,r><x,y,c,r><x,y,c,r>. 给出 ...

  4. 2018.06.29 NOIP模拟 Gcd(容斥原理)

    Gcd 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出n个正整数,放入数组 a 里. 问有多少组方案,使得我从 n 个数里取出一个子集,这个子集的 gcd 不为 1 ,然后我再从 ...

  5. 2018.10.26 NOIP模拟 图(最小生成树+线段树合并)

    传送门 首先最开始说的那个一条路径的权值就是想告诉你两个点之间的贡献就是瓶颈边的权值. 那么肯定要用最小生成树算法. 于是我考场上想了30min+30min+30min+的树形dpdpdp 发现转移是 ...

  6. 2018.10.26 NOIP模拟 性感手枪(搜索)

    传送门 vis[x][y]vis[x][y]vis[x][y]记录这个点是否在之前被搜过,且被搜过的坐标是什么. 然后搜索的时候记录一个循环的下标和不循环的下标就行了. 代码

  7. 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)

    题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...

  8. 2018.06.29 NOIP模拟 Minimum(最小生成树)

    Minimum 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一幅由 n 个点 m 条边构成的无向带权图. 其中有些点是黑点,另外点是白点. 现在每个白点都要与他距离最近的所有黑 ...

  9. 2018.06.29 NOIP模拟 1807(简单递推)

    1807 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一个由数字('0'-'9')构成的字符串.我们说一个子序列是好的,如果他的每一位都是 1.8.0.7 ,并且这四个数字按照 ...

随机推荐

  1. laravel框架目录结构详解

  2. vue 登录前做校验this.$router.push(location)

    有很多按钮在执行跳转之前,还会执行一系列方法,这时可以使用 this.$router.push(location) 来修改 url,完成跳转 例如:登录按钮,点击时需要先判断验证码等是否正确,此时

  3. IntelliJ IDEA 运行 Maven 项目

    1.官方文档说IntelliJ IDEA已经自身集成了maven,则不用劳心去下载maven 2.导入一个程序,看是否是maven程序的关键在于工程之中有没有pom.xml这个文件,比如这里   3. ...

  4. Number & Maths类

    Java Number & Math 类 一般地,当需要使用数字的时候,我们通常使用内置数据类型,如:byte.int.long.double 等. 实例 int a = 5000;float ...

  5. WorkerMan源码分析(resetStd方法,PHP中STDIN, STDOUT, STDERR的重定向)

    WorkerMan中work.php中 resetStd 方法中代码如下 public static function resetStd() { if (!static::$daemonize || ...

  6. go语言使用go-sciter创建桌面应用(六) Element元素操作和Event事件响应

    详细的文档请看下面两个链接: https://sciter.com/docs/content/sciter/Element.htm https://sciter.com/docs/content/sc ...

  7. Task.WaitAll代替WaitHandle.WaitAll

    Task.Waitall阻塞了当前线程直到全完.whenall开启个新监控线程去判读括号里的所有线程执行情况并立即返回,等都完成了就退出监控线程并返回监控数据. task.Result会等待异步方法返 ...

  8. 在ubuntu16.04编译安装httperf

    在网上偶尔看到httperf可以在测试中使用.网上苦苦找不到ubuntu编译安装的方法.自己琢磨了一下,现在总结如下: apt install httperf vim /etc/security/li ...

  9. Android 异步加载数据 AsyncTask异步更新界面

    官方文档:     AsyncTask enables proper and easy use of the UI thread. This class allows to perform backg ...

  10. <history> 特别报道:Google离职富翁们都在干什么?

    特别报道:Google离职富翁们都在干什么? 时间:2008-01-23 10:16:47作者:CNET科技资讯网 本文关键词:Google CNET科技资讯网1月23日国际报道 假如你拥有1千万或1 ...