题目找链接

题意:

  如果数a能被a中的每一位数整除(0除掉),则称a是一个beautiful number,求一个区间内的beautiful numbers的个数。

分析:

  首先,很显然,l到r的所有beautiful numbers(以下写b n吧,有点长)等于0到r的b n个数减去0到l-1的b n的个数,这个不用证明吧。当然也很好证。然后我们只要能在时间允许的范围内求0到某个数的b n的数量就可以了。

  怎么求能?我们把它转化到树上,先举个例子:如果要求0到23的b n的数量,那么我们假设有一个根为0的树,0这个结点有儿子0 1 2,然后0有儿子0 1 2 3 4 5 6 7 8 9,1有儿子0 1 2 3 4 5 6 7 8 9,2有儿子0 1 2 3,那么我们只要从根开始读,一直读到叶子节点(例如一直向最左走我们就读到000,一直向最右走就读到023,然后中间可以读到这两个数中间所有的数,不重且不漏),到每一个叶子节点记录一下这个数可不可以被经过的所有节点整除就好了,这不还是暴力吗。。。先别急,慢慢来,这样我们先想一下怎么转移,如果他能被x,y整除,一定能被其最小公倍数整除,当然,反过来说也成立,那我们只需要记录途径数字的最小公倍数就可以直接判断这样走的数能不能被所有位数整除。我们定义Dp[i][ha][k]表示所有过第i个节点的b n数(当然已经给节点编号),ha表示我们已经读到的数,于是我们有了转移方程:

  Dp[i][ha][k]=sum{Dp[son[i][ha*10+val[son[i][j]]][j]][divisor(k,val[son[i][j]])]};

  就不写公式了,大家应该可以看懂,divisor表示最小公倍数,val[i]表示第i个节点上写的数字,son[i][j]表示第i个节点的第j个儿子。

  其实到这里,基本的思路就有了,但是解决问题还差一点,首先,这么大的数组开不下,然后就是时间复杂度接受不了。于是我们要进行优化。

  其实大家会发现,很多棵子数是相似的,那是不是有些子树可以只求一边呢,当然可以,首先我们要明确一点,我们所有可能用到的k都有x%2520同余x(mod k),于是我们想一想,如果到某个节点读出的数字是0252025200,其实和读到0000252000(位数要相等)最后找到的状态数没什么不同(前题是两个节点的子树都是满的),那么我们就可以把ha表示为读到的数字%2520,于是此时你会发现,这个点的b n的数量和这个点的i只没有什么关系,所有这一维可以省掉,但是还有问题,就是虽然0000同余00000(mod 2520)但是并不等价,为什么呢,因为子树大小已经不一样了(及还需读的位数不一样),那么我们就可应再加一维表示还要读的数字的数量,然后进行记忆话搜索就可以了。

  现在再重新说一下状态:Dp[i][j][k]表示还剩i个数字没有读,读到的数字数字%2520为j且走过的所有的数的最小公倍数为k读完满的子树之后可以找到b n的数量。注意,刚才我并没有对k进行描述,但现在有了,因为刚才k并不是状态,只是记录一下到这里的最小公倍数,也就是说可以没有k这一维。而这里我们不再区分节点,所有要记录k,k相同才等价。(要想明白是为什么等价)

  说到这里,大家应该都知道该怎么做了但是Dp数组仍然有点大,还能不能缩小一下,可以:离散化,k可以取到的值其实是要小于2520的,我们只要找出可能取到的值就可以了。

  还有就是当然边界特殊处理。

  最后是他的时间复杂度,有人说是O(玄学)。。。其实还是有保证的,首先,Dp中每个值只会算一次,边界最多18层,每层最多有10个儿子,而儿子只有一个是边界,所有还是可以保证复杂度的。

  部分细节见代码注释。

  最后看代码吧:

#include <cstdio>
#include <cstring>
long long Dp[][][];
int mod=;//1-9的最小公倍数
long long Gcd(long long a,long long b){
if(!b)
return a;
return Gcd(b,a%b);
}
long long B(long long a,long long b){//求最小公倍数
if(!a||!b)//特殊处理0
return a+b;
return (a/Gcd(a,b))*b;
}
int w[];//记录每一位以处理边界
int li[];
long long dp(int len,int yu,int BB,bool bi){//开始dp
if(len==){//到达叶子节点
if(yu%BB==)
return ;
else
return ;
}
if(!bi&&Dp[len][yu][li[BB]]!=-)//已经有等价情况处理过了
return Dp[len][yu][li[BB]];
int j;
if(bi)
j=w[len];
else
j=;
long long ans=;
for(int i=;i<j;i++)
ans+=dp(len-,(yu*+i)%mod,B(BB,i),);
ans+=dp(len-,(yu*+j)%mod,B(BB,j),bi);
if(!bi)
Dp[len][yu][li[BB]]=ans;
return ans;
}
long long Cl(long long a){
int len=;
while(a){
len++;
w[len]=a%;
a/=;
}
return dp(len,,,);//算出位数进行处理
}
int main(){
memset(Dp,-,sizeof(Dp));//0可能会tle,因为可能有0的一些节点要算好多遍
int t;
scanf("%d",&t);
int al=;
for(int i=;i<=;i++)//离散化
if(%i==){
al++;
li[i]=al;
}
for(int i=;i<=t;i++){
long long l,r;
scanf("%I64d%I64d",&l,&r);//题目说不用%lld
printf("%I64d\n",Cl(r)-Cl(l-));
}
return ;
}

beautiful numbers树形dp or 数位dp的更多相关文章

  1. BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP

    BZOJ_1662_[Usaco2006 Nov]Round Numbers 圆环数_数位DP Description 正如你所知,奶牛们没有手指以至于不能玩“石头剪刀布”来任意地决定例如谁先挤奶的顺 ...

  2. 【BZOJ】1662: [Usaco2006 Nov]Round Numbers 圆环数(数位dp)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1662 这道题折腾了我两天啊-!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! 果然 ...

  3. 数位dp初步——数位dp的两种方式

    数位dp:一类统计区间[L,R]内某种符合规定的数字个数的题目.特征是R的范围会很大,O(N)范围内无法完成. 一般而言,解决这类题目有两种方式,一种是递推,另一种是记忆化搜索. 递推: 1)利用dp ...

  4. 区间DP,数位DP

    dp(动态规划)顾名思义便是动态的一种规划,而这种规划往往会跟状态,状态转移方程,记忆化搜索扯上关系,当然DP也是各个OI考试的必考点和常考点,在毒瘤出题人的折磨下,出现了许许多多的动态规划,有线性, ...

  5. BestCoder Round #75 King&#39;s Order dp:数位dp

    King's Order Accepts: 381 Submissions: 1361 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 655 ...

  6. CF908G New Year and Original Order(DP,数位 DP)

    又一次降智…… (数位 DP 原来可以写这么短,学到了) 问题可以转化为求数位中 $\ge k$ 的有恰好 $j$ 位的数的个数.设为 $c_{j,k}$. 那么答案就是:(考虑把 $k$ 的贡献拆开 ...

  7. [Codefroces401D]Roman and Numbers(状压+数位DP)

    题意:给定一个数,求将该数重新排列后mod m==0的方案数 重新排列就考虑到用到哪些数,以及此时mod m的值 于是dp[i][j]表示状态i中mod m==j的方案数 注意:转移的时候只要找到一种 ...

  8. SPOJ BALNUM Balanced Numbers 平衡数(数位DP,状压)

    题意: 平衡树定义为“一个整数的某个数位若是奇数,则该奇数必定出现偶数次:偶数位则必须出现奇数次”,比如 222,数位为偶数2,共出现3次,是奇数次,所以合法.给一个区间[L,R],问有多少个平衡数? ...

  9. [转]数位dp小记

    转载自:http://blog.csdn.net/guognib/article/details/25472879 参考: http://www.cnblogs.com/jffifa/archive/ ...

随机推荐

  1. 为什么我觉得 Java 的 IO 很复杂?

    初学者觉得复杂是很正常的,归根结底是因为没有理解JavaIO框架的设计思想: 可以沿着这条路想一想: 1,学IO流之前,我们写的程序,都是在内存里自己跟自己玩.比如,你声明个变量,创建个数组,创建个集 ...

  2. 关于linux免密登录及ssh客户端的使用

    操作系统环境: CentOS Linux release 7.7.1908 (Core) 1.首先在linux服务器上,使用ssh-keygen命令生成密钥对文件(一直回车即可,默认使用rsa算法), ...

  3. opencl(7) 内核执行命令入队]工作组、工作项

    1:将内核执行命令入队(该命令可被多个工作项执行) cl_int clEnqueueNDRangeKernel( cl_command_queue command_queue, cl_kernel k ...

  4. tensorflow2.0学习笔记第一章第三节

    1.3鸢尾花数据读入 # 从sklearn包datasets读入数据 from sklearn import datasets from pandas import DataFrame import ...

  5. input搜索框的搜索功能

    如图,想要实现输入关键词,点击搜索按钮或者回车键都能进行搜索并返回. html部分代码如下: js部分—— function entersearch(){ var event = window.eve ...

  6. Uber基于Apache Hudi构建PB级数据湖实践

    1. 引言 从确保准确预计到达时间到预测最佳交通路线,在Uber平台上提供安全.无缝的运输和交付体验需要可靠.高性能的大规模数据存储和分析.2016年,Uber开发了增量处理框架Apache Hudi ...

  7. 在Asp.NET Core中如何优雅的管理用户机密数据

    在Asp.NET Core中如何优雅的管理用户机密数据 背景 回顾 在软件开发过程中,使用配置文件来管理某些对应用程序运行中需要使用的参数是常见的作法.在早期VB/VB.NET时代,经常使用.ini文 ...

  8. JavaScript 定时器 取消定时器

    感谢:链接(视频讲解很清晰) 定时器:作用主要是一定时间间隔后,做出相关的变化,例如图片轮播. 目录 两种定时器的使用 两种定时器区别 取消定时器的方法 两种定时器的使用: 方法一:setTimeou ...

  9. mysql字符串类型(char,varchar)

    原文链接:https://blog.csdn.net/puqutogether/article/details/45648879 MySQL中的字符串有两个常用的类型:char和varchar,二者各 ...

  10. ComplexHeatmap|根据excel表绘制突变景观图(oncoplot)

    本文首发于“生信补给站”:https://mp.weixin.qq.com/s/8kz2oKvUQrCR2_HWYXQT4g 如果有maf格式的文件,可以直接oncoplot包绘制瀑布图,有多种展示和 ...