题目链接

题意

定义一个数字\(x\)是\(beautiful\ number\)当且仅当\(x\)可以被其十进制表示下所有非\(0\)位置的数整除。

例如\(24\)是一个\(beautiful\ number\),因为他可以被\(2\)和\(4\)整除。

而\(28\)不是一个\(beautiful\ number\),因为他不能被\(8\)整除

给出两个数字\(L,R\; (1 \le L\le R \le 10^{18})\)

求出区间\([L,R]\)内有多少\(beautiful\ number\)

思路

首先显然的数位\(dp\)

先不考虑空间和时间问题

要让一个数字\(x\)整除所有数位上的数字。其实也就是要整除这些数字的最小公倍数\((lcm)\)。

用\(f[i][j][k]\)表示当前到了第\(i\)位,当前数字为\(j\;\) (先不管能否空间是否足够)。所选数字的\(lcm\)为\(k\)的方案数。

搜到最后看一下\(lcm\)是否整除\(j\)即可。

然后考虑空间问题。

在\(f[i][j][k]\)中,\(i\)是\(18\)左右,\(j\)是\(10^{18}\),\(k\)最大是\(2520\)(\(2520\)是\(1\) ~ \(9\)的\(lcm\))

考虑优化一下\(j\)这一维。

显然所有可能的\(lcm\)都是\(2520\)的因数。

而比较显然的

\[x \% p = x \% kp \% p
\]

所以我们可以把\(j\)那一维的数以\(2520\)为模数\(hash\)一下。

然后优化\(k\)那一维。

枚举一下可以发现。\(1\)~\(9\)的所有可能组合中。\(lcm\)的种类其实只有\(50\)种左右。所以就可以把最后一维压成\(50\)左右

然后就可以愉快的数位\(dp\)啦!

代码

/*
* @Author: wxyww
* @Date: 2019-03-17 08:30:41
* @Last Modified time: 2019-03-17 19:36:46
*/
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<ctime>
using namespace std;
typedef long long ll;
const int LCM = 2520;
#define int ll
ll read() {
ll x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') {
if (c == '-') f = -1;
c = getchar();
}
while (c >= '0' && c <= '9') {
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}
ll L, R;
int dy[100], pk[LCM + 100];
int get_lcm(int x, int y) {
if (!y) return x;
return x * y / __gcd(x, y);
}
namespace BF2 {
int pos, f[20][3000][60], a[20];
ll dp(ll p, ll now, ll lcm, int lim) {
if (!p) return now % dy[lcm] == 0;
if (f[p][now][lcm] != -1 && !lim) return f[p][now][lcm];
int up = 9;
if (lim) up = a[p];
int tmp = 0;
for (int i = 0; i <= up; ++i)
tmp += dp(p - 1, ((now * 10 + i) % LCM), pk[get_lcm(dy[lcm], i)], lim & i == up);
if (!lim) f[p][now][lcm] = tmp;
return tmp;
}
ll solve(ll x) {
pos = 0;
while (x) {
a[++pos] = x % 10; x /= 10;
}
return dp(pos, 0, 1, 1);
}
void main() {
cout << solve(R) - solve(L - 1) << endl;
}
}
signed main() {
int T = read();
memset(BF2::f, -1, sizeof(BF2::f));
int cnt = 0;
for (int i = 1; i <= LCM; ++i) {
if (LCM % i == 0) {
dy[++cnt] = i; pk[i] = cnt;
}
}
while (T--) {
L = read(), R = read();
BF2::main();
}
return 0;
}

CF55D Beautiful numbers的更多相关文章

  1. 洛谷 CF55D Beautiful numbers 解题报告

    CF55D Beautiful numbers 题意 \(t(\le 10)\)次询问区间\([l,r](1\le l\le r\le 9\times 10^{18})\)中能被每一位上数整除的数的个 ...

  2. [暑假集训--数位dp]cf55D Beautiful numbers

    Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer numb ...

  3. CF55D Beautiful numbers 题解

    题目 Volodya is an odd boy and his taste is strange as well. It seems to him that a positive integer n ...

  4. cf55D. Beautiful numbers(数位dp)

    题意 题目链接 Sol 看到这种题就不难想到是数位dp了. 一个很显然的性质是一个数若能整除所有位数上的数,则一定能整除他们的lcm. 根据这个条件我们不难看出我们只需要记录每个数对所有数的lcm(也 ...

  5. CF55D Beautiful numbers (数位dp)

    题目链接 题解 一个数能被一些数整除,那么一定被这些数的\(lcm\)整除 那么我们容易想到根据\(lcm\)设状态 我们可以发现有用的\(lcm\)只有\(48\)个 那么按照一般的数位\(dp\) ...

  6. 【数位DP】CF55D Beautiful numbers

    $dp[x][p][pp]$表示第x位,当前已有数字mod 2520(1~9数字的lcm)为p,当前各位数字的lcm为pp 观察到数组太大,考虑压缩,第三维lcm最多只有9个数字,打表发现最多只有48 ...

  7. 【CF55D】Beautiful numbers(动态规划)

    [CF55D]Beautiful numbers(动态规划) 题面 洛谷 CF 题解 数位\(dp\) 如果当前数能够被它所有数位整除,意味着它能够被所有数位的\(lcm\)整除. 所以\(dp\)的 ...

  8. 【CF55D】Beautiful numbers

    [CF55D]Beautiful numbers 题面 洛谷 题解 考虑到如果一个数整除所有数那么可以整除他们的\(lcm\),而如果数\(x\)满足\(x\bmod Lcm(1,2...,9)=r\ ...

  9. CodeForces 55D Beautiful numbers

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

随机推荐

  1. C++ 浅拷贝与深拷贝探究

    C++浅拷贝与深拷贝探究 浅拷贝与深拷贝的概念是在类的复制/拷贝构造函数中出现的. 拷贝构造函数使用场景 对象作为参数,以值传递方式传入函数(要调用拷贝构造函数将实参拷贝给函数栈中的形参) 对象作为返 ...

  2. angular应用容器化部署

    angular 应用容器化部署 Intro 我自己有做一个个人主页,虽然效果不怎么样(不懂设计的典型程序猿...),但是记录了我对于前端框架及工具的一些实践, 从开始只有一个 angularjs 制作 ...

  3. Android PAI (PlayAutoInstall)预装APK 功能

    最近刚找到工作,是手机方案公司,刚接触手机系统预装的APP,以及解决方案MTK平台下预装APP的bug,也接触到了Launcher的东西. 然后接触到了第一个需求 PAI预装APK功能 下面是我用到的 ...

  4. C# 一般处理程序ashx接收服务端post过来json数据

    这个和前端js的接收方式有点不一样,前端接收用request.form["xxx"]即可

  5. python3 dict(字典)

    clear(清空字典内容) stu = { 'num1':'Tom', 'num2':'Lucy', 'num3':'Sam', } print(stu.clear()) #输出:None copy( ...

  6. MFC桌面电子时钟的设计与实现

    目录 核心技术 需求分析 程序设计 程序展示 (一)核心技术 MFC(Micosoft Foundation Class Libay,微基础类库)是微基于Windows平台下的C++类库集合,MFC包 ...

  7. const int *p;int *const p;区别及用法

    在单片机程序设计中,我们经常会用到const这个关键字,在有些单片机的编译器中可能会是code(比如51系列单片机),但我们在学习C语言的时候,首先还是先学到的const.我们知道,const关键字的 ...

  8. 英语进阶系列-A06-本周总结

    本周总结 目录Content 英语进阶系列-A01-再别康桥 英语进阶系列-A02-英语学习的奥秘 英语进阶系列-A03-英语升级练习一 英语进阶系列-A04-英语升级练习二 英语进阶系列-A05-英 ...

  9. Linux下配置nfs并远程挂载实战探讨

    简单介绍: nfs是网络文件系统,允许一个节点通过网络访问远程计算机的文件系统,远程文件系统可以被直接挂载到本地,文件操作和本地没有区别,如果是局域网的nfs那么io的性能也可以保证 nfs是Netw ...

  10. 2019年桌面Linux需要做好的7件事

    2019年桌面Linux需要做好的7件事 新的一年已经到来,这意味着又一年过去了,Linux还是没有发现自己主宰了桌面.Linux在许多方面做得非常好,在接下来的几周,我们将研究一些最适合您各种需求的 ...