题目背景

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. 100-days:nine

    Title: Boeing(波音飞机) crash isolates FAA as(伴随,随着) China leads push against Max(出事机型,即737 Max) crash n ...

  2. express 学习札记

    Enjoy yourself! 祝你玩得开心! I have no idea. 我没有头绪. I just made it! 我做到了!  I’ll see to it 我会留意的. Express ...

  3. 21 pythone【入门指南】:string

    string是很基础的数据结构,来看看string有哪些常用的操作. #!/bin/python #!---encoding: UTF- s = 'abcdefg' #concat s1 = s + ...

  4. php解析优酷网上的视频资源去广告

    1.过程原理解析: 一.准备工作 所谓工欲善其事必先利其器,做好破解的准备工作会令你事半功倍. 1.首先准备一个Http抓包工具,PC上推荐Fiddler或者Postman,iOS上推荐Surge 2 ...

  5. 用Python监听鼠标和键盘事件

    PyHook是一个基于Python的“钩子”库,主要用于监听当前电脑上鼠标和键盘的事件.这个库依赖于另一个Python库PyWin32,如同名字所显示的,PyWin32只能运行在Windows平台,所 ...

  6. [Z]scp example

    https://www.cnblogs.com/autumnvivi/articles/3447964.html

  7. nginx + fastdfs 的开机自启动

    虚拟机每次启动之后都要重新启动一下fastdfs 和 nginx服务,比较麻烦,所以增加开机自启动: 编辑 /etc/rc.d/rc.local 文件,增加启动项: 1.编辑文件 vim /etc/r ...

  8. 探索未知种族之osg类生物---呼吸分解之advance

    回顾 我们用了两节的内容才堪堪讲解完ViewerBase::frame()函数中调用的realize()---Viewer:: realize()函数.我们简单的总结就是Viewer:: realiz ...

  9. 洛谷1462(重题1951) 通往奥格瑞玛的道路(收费站_NOI导刊2009提高(2))

    1462原题链接 1951原题链接 显然答案有单调性,所以可以二分答案,用\(SPFA\)或\(dijkstra\)跑最短路来判断是否可行即可. 注意起点也要收费,\(1462\)数据较水,我一开始没 ...

  10. Linux 终端设备

    <Linux终端设备详解> https://www.cnblogs.com/shineshqw/articles/2423989.html