题意

求[X,Y]区间内能被其各位数(除0)均整除的数的个数。

CF 55D

有些时候因为问题的一些“整体性”而导致在按位统计的过程中不能顺便计算出某些量,所以只能在枚举到最后一位确定数字时才能计算相应的统计。

在本题中,我们无法在过程中确定到底有哪些数位,以及这个数本身,所以这些计算都要放在最后。所以首先我们需要参数num传递当前搜索确定的数字,以及判断该数字是否能被其数位整除。而判断各位整除只要数字整除各位数的最小公倍数lcm即可。

但我们随后发现了问题:各位数最小公倍数最大可能为lcm(1..9)=2520,而某个数最大为1018显然不能直接存。当然,我们可以用这个数%2520来代替数本身,但这样2520*2520*20的空间也不够。我们可以发现其实各位数的最小公倍数远没有2520个,而是2520的所有约数个数,不到50个。所以我们可以利用hash将空间缩至2520*50*20。这样,CF 55D便迎刃而解了(详见下面CF 55D代码)。

SPOJ JZPEXT

再来看CF 55D的升级版……两道都是7k+出的题只是这道更丧心病狂……全世界只有21个人AC……题目本身并没有变,只是限制了代码长度为1k!并且,数据组数增至104

首先需要的是强劲的缩代码能力,这个不说了。我们发现,其实每个数2520的空间也浪费了,每次向下枚举一位都是(rem * 10 + i) mod 2520。。那么到最后一位的时候先给了之前的数2和5两个因子。。整个能不能多整除一个2和5只取决于i。。因此。。之前只需要记录模252的余数就可以了。。

最后需要注意的是需要把lcm和(rem*10+i)%252都预处理一下……

代码

【CF 55D】
[cpp]
#include <cstdio>
#include <cmath>
#include <cstring>
#include <algorithm>
#define MEM(a,b) memset(a,b,sizeof(a))
using namespace std;
typedef long long LL;
int num[20], hash[2550];
LL dp[20][2550][55];
int gcd(int a, int b){
return b?gcd(b, a%b):a;
}
int cal_lcm(int a, int b){
return a/gcd(a, b)*b;
}
void init(){
MEM(dp, -1);
int n=2520, id=0;
for (int i = 1; i*i <= n; i ++){
if (n%i==0){
hash[i] = id++;
if (i != n/i){
hash[n/i] = id ++;
}
}
}
}
LL dfs(int pos, int mod, int lcm, bool limit){
if (pos == -1) return (mod%lcm==0);
if (!limit && ~dp[pos][mod][hash[lcm]]) return dp[pos][mod][hash[lcm]];
int end = limit?num[pos]:9; LL res = 0;
for (int i = 0; i <= end; i ++){
res += dfs(pos-1, (mod*10+i)%2520, i?cal_lcm(lcm, i):lcm, limit && (i==end));
}
return limit?res:dp[pos][mod][hash[lcm]]=res;
}
LL cal(LL x){
int i = 0;
while(x){
num[i++] = x%10;
x/=10;
}
return dfs(i-1, 0, 1, 1);
}
int main(){
init();
int t;
scanf("%d", &t);
while(t --){
LL l, r;
scanf("%lld %lld", &l, &r);
printf("%lld\n", cal(r)-cal(l-1));
}
return 0;
}
[/cpp]
【SPOJ JZPEXT】
[cpp]
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
int nu[20],h[2522],mo[255][10],mu[255][10],lc[2522][10];
LL f[20][55][255];
LL dfs(int p,int m,int l,bool li){
if(p==-1)return (m%l==0);
if(!li && ~f[p][h[l]][m]) return f[p][h[l]][m];
int e=li?nu[p]:9;LL r=0;
for (int i=0;i<=e;i++){r+=dfs(p-1,p?mo[m][i]:mu[m][i],lc[l][i],li&&(i==e));}
return li?r:f[p][h[l]][m]=r;
}
LL cal(LL x){
int i=-1;
while(x){nu[++i]=x%10;x/=10;} ++i;
return dfs(i-1,0,1,1);
}
int main(){
memset(f,-1,sizeof(f));
int i,j,id=0;
for (i=0;i<=252;i++)for (j=0;j<10;j++){mu[i][j]=i*10+j;mo[i][j]=mu[i][j]%252;}
for (i = 0; i <= 2520; i ++){
if (i>0 && 2520%i==0){h[i]=id++;}
for(j=0;j<10;j++)lc[i][j]=j?i*j/__gcd(i,j):i;
}
int t;
scanf("%d",&t);
while(t--){
LL l,r;
scanf("%lld%lld",&l,&r);
printf("%lld\n",cal(r)-cal(l-1));
}
return 0;
}
[/cpp]

CodeForces 55D Beautiful numbers (SPOJ JZPEXT 数位DP)的更多相关文章

  1. CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)

    传送门 参考资料: [1]:CodeForces 55D Beautiful numbers(数位dp&&离散化) 我的理解: 起初,我先定义一个三维数组 dp[ i ][ j ][ ...

  2. Codeforces 55D. Beautiful numbers(数位DP,离散化)

    Codeforces 55D. Beautiful numbers 题意 求[L,R]区间内有多少个数满足:该数能被其每一位数字都整除(如12,24,15等). 思路 一开始以为是数位DP的水题,觉得 ...

  3. codeforces 55D - Beautiful numbers(数位DP+离散化)

    D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

  4. CodeForces - 55D - Beautiful numbers(数位DP,离散化)

    链接: https://vjudge.net/problem/CodeForces-55D 题意: Volodya is an odd boy and his taste is strange as ...

  5. CodeForces - 55D Beautiful numbers —— 数位DP

    题目链接:https://vjudge.net/problem/CodeForces-55D D. Beautiful numbers time limit per test 4 seconds me ...

  6. CodeForces 55D Beautiful numbers(数位dp+数学)

    题目链接:http://codeforces.com/problemset/problem/55/D 题意:一个美丽数就是可以被它的每一位的数字整除的数. 给定一个区间,求美丽数的个数. 显然这是一道 ...

  7. CodeForces 55D Beautiful numbers(数位dp)

    数位dp,三个状态,dp[i][j][k],i状态表示位数,j状态表示各个位上数的最小公倍数,k状态表示余数 其中j共有48种状态,最大的是2520,所以状态k最多有2520个状态. #include ...

  8. Codeforces - 55D Beautiful numbers (数位dp+数论)

    题意:求[L,R](1<=L<=R<=9e18)区间中所有能被自己数位上的非零数整除的数的个数 分析:丛数据量可以分析出是用数位dp求解,区间个数可以转化为sum(R)-sum(L- ...

  9. CodeForces 55D Beautiful numbers

    D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...

随机推荐

  1. ruby中的可调用对象--方法

    上一篇讲了ruby中的可调用对象proc和lambda,他们都是块转换成的对象.ruby中的可调用对象还有方法.通过使用method方法,并且以方法名作为参数(字符串或者符号),就可以得到一个方法对象 ...

  2. 论文笔记:空间变换网络(Spatial Transformer Networks)

    2015, NIPS Max Jaderberg, Karen Simonyan, Andrew Zisserman, Koray Kavukcuoglu Google DeepMind 为什么提出( ...

  3. Web服务器实现文件传输程序设计

    总体概括来说就是设计一个Web服务器的流程,将执行流程分为简单的步骤,每个步骤作为一个模块来实现. 1.整体设计 服务器程序发送文件给客户端或者从客户端接收文件,每次通信只能做一次文件传输,传输完毕后 ...

  4. ABP官方文档翻译 2.4 日志

    日志 服务端 获取记录器 基类日志记录器 配置 Abp.Castle.Log4Net包 客户端 服务端 ABP使用Castle Windsor`s 日志设备.它可以使用不同的日志类库:Log4Net, ...

  5. ubuntu18.04 64bit如何安装docker

    注:参考自https://docs.docker.com/install/linux/docker-ce/ubuntu/ 1.卸载旧版本docker(如果之前安装了) sudo apt-get rem ...

  6. Oracle修改表结构

    --添加字段 alter table [tablename] add  [column name] [column data type]; --修改字段数据类型 alter table [tablen ...

  7. LeetCode——Decode String

    Question Given an encoded string, return it's decoded string. The encoding rule is: k[encoded_string ...

  8. Exception in thread "main" redis.clients.jedis.exceptions.JedisDataException

    这个版本默认是开启了保护模式,进入redis的文件夹下的src 输入(前提是得开启redis服务): ./redis-cli config set protected-mode "no&qu ...

  9. [笔记整理]SQL Server 索引碎片 和 重建索引

    铺垫知识点: 数据库存储本身是无序的,建立了聚集索引,会按照聚集索引物理顺序存入硬盘.既键值的逻辑顺序决定了表中相应行的物理顺序 多数情况下,数据库读取频率远高于写入频率,索引的存在 为了读取速度牺牲 ...

  10. redis_port.py

    !/usr/bin/env python import os import json import simplejson as json t=os.popen("""su ...