2018.06.26 NOIP模拟 号码(数位dp)
题目背景
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)的更多相关文章
- 2018.10.26 NOIP模拟 瓶子 (dp/贪心)
传送门 正解是dp并不想去想了. 自己yy了一个贪心拿了95pts95pts95pts,唯一没过的点还只有一个地方错了,面向数据变成之后过啦! 所以我讲讲如何贪心. 考虑到最后都只会合并成一种颜色,所 ...
- 2018.06.26 NOIP模拟 纪念碑(线段树+扫描线)
题解: 题目背景 SOURCE:NOIP2015−GDZSJNZXSOURCE:NOIP2015-GDZSJNZXSOURCE:NOIP2015−GDZSJNZX(难) 题目描述 2034203420 ...
- 2018.06.29 NOIP模拟 边的处理(分治+dp)
边的处理(side.cpp) [问题描述] 有一个 n 个点的无向图,给出 m 条边,每条边的信息形如<x,y,c,r><x,y,c,r><x,y,c,r>. 给出 ...
- 2018.06.29 NOIP模拟 Gcd(容斥原理)
Gcd 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出n个正整数,放入数组 a 里. 问有多少组方案,使得我从 n 个数里取出一个子集,这个子集的 gcd 不为 1 ,然后我再从 ...
- 2018.10.26 NOIP模拟 图(最小生成树+线段树合并)
传送门 首先最开始说的那个一条路径的权值就是想告诉你两个点之间的贡献就是瓶颈边的权值. 那么肯定要用最小生成树算法. 于是我考场上想了30min+30min+30min+的树形dpdpdp 发现转移是 ...
- 2018.10.26 NOIP模拟 性感手枪(搜索)
传送门 vis[x][y]vis[x][y]vis[x][y]记录这个点是否在之前被搜过,且被搜过的坐标是什么. 然后搜索的时候记录一个循环的下标和不循环的下标就行了. 代码
- 2018.06.27 NOIP模拟 节目(支配树+可持久化线段树)
题目背景 SOURCE:NOIP2015-GDZSJNZX(难) 题目描述 学校一年一度的学生艺术节开始啦!在这次的艺术节上总共有 N 个节目,并且总共也有 N 个舞台供大家表演.其中第 i 个节目的 ...
- 2018.06.29 NOIP模拟 Minimum(最小生成树)
Minimum 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一幅由 n 个点 m 条边构成的无向带权图. 其中有些点是黑点,另外点是白点. 现在每个白点都要与他距离最近的所有黑 ...
- 2018.06.29 NOIP模拟 1807(简单递推)
1807 题目背景 SOURCE:NOIP2015-SHY-2 题目描述 给出一个由数字('0'-'9')构成的字符串.我们说一个子序列是好的,如果他的每一位都是 1.8.0.7 ,并且这四个数字按照 ...
随机推荐
- 199. Binary Tree Right Side View (Tree, Stack)
Given a binary tree, imagine yourself standing on the right side of it, return the values of the nod ...
- c# 键值对的方式post提交
DataContractJsonSerializer jsQcData = new DataContractJsonSerializer(typeof(DATA<data>));//DAT ...
- [剑指Offer]58-翻转字符串
题目一 翻转单词顺序 题意 输入一个英文句子,翻转句子中的单词的顺序,但单词内自负的顺序不变.标点符号和普通字母一样处理. 例: 输入:"I am a student." 输出:& ...
- iOS版本设置
Base SDK指的是当前编译所用的SDK 版本: iOS Deployment Target指的是,编译后的 app 可在 终端的哪个 版本上运行. 设置方法: 点击xcode工程左侧项目名称-&g ...
- 20165315 预备作业3 Linux安装及学习
20165315 预备作业3 Linux安装及学习 一.在自己笔记本上安装Linux操作系统 因为对操作电脑的不熟悉,我在第一项任务上就花费了一定的时间,在安装过程有如下问题: 我的电脑是苹果公司的M ...
- webpack(一) 安装使用
(一)webpack的安装 webpack是基于node.js,因此需要安装node.js. 安装好node.js 后,全局安装webpack,命令如下 npm install webpack -g ...
- oracle 11g用exp无法导出空表的解决方案
racle 11g中有个新特性,当表无数据时,不分配segment,以节省空间,当我们用exp导出空表时,无法导出. 解决方法是两个方面, 一是处理现有的空表,让其能导出: 二是设置参数,让后续的新的 ...
- angular2.0学习笔记2.创建hello world项目
1.打开终端命令行窗口 2.切换到指定目录 E:\cd myobject 3.创建新项目 ng new angular2-helloworld 4.创建成功后,在angular2-helloworld ...
- GM Tech 2 works with Hummer Yes or No
This is about GM Tech 2 scan tool for Hummer troubleshooting and programming. Can I have a cheap Tec ...
- 20172306《java程序设计与数据结构》第六周学习总结
20172306<Java程序设计>第六周学习总结 教材学习内容总结 第八章关键学习了数组的相关内容.我觉得主要分一下几点: 1.索引是从0开始,要区分好索引值和个数值.0的索引处是第一个 ...