CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)
参考资料:
[1]:CodeForces 55D Beautiful numbers(数位dp&&离散化)
题意:
求一个区间内的Beautiful numbers有多少个。Beautiful numbers指:一个数能整除所有组成它的非0数字。
例如15可以被1和5整除,所以15是Beautiful numbers。
我的理解:
起初,我先定义一个三维数组 dp[ i ][ j ][ k ]:来到 i 位置时,所有非零数的lcm = j,当前数位 k 时含有的 Beautiful numbers 的个数。
但是,由题意得,当前的数 k 可以是个很大的数(9e18),数组根本就开不下,那怎么办呢?
将当前的数 hash 一下,如何hash呢?
假设 a,b,c,d 为[0,9]的数,那么不存在另一个 a',b',c',d'
使得 a*11+b*13+c*17+d*19 = a' *11+b' *13+c' *17+d' *19;
也就是说,这 19 位数分别乘以大于10 的互不相等的前19个素数是不会存在重数的;
那么,hash完后,最大的数才7000多,那么开个 dp[20][50][8000] 的数组绰绰有余;
但问题来了,既然每个数的 hash 值都不想等,那,哪来的记忆化搜索?
所以说,这就是赤裸裸的暴力!!!!!!
so,举足无措,只好参考大佬博客辽。
下面具体说说我的理解:
首先解释一下上述博客中给出的公式 sum%(x*n)%x == sum%x 的证法以及作用;
证明:
sum%(x*n) = sum-(int)(sum / (x*n) )*(x*n);
sum%(x*n)%x = [sum-(int)(sum / (x*n) )*(x*n) ] % x = sum%x - 0 = sum % x;
那,接下来就要看看要怎么用这个公式了,预处理出 1~9的所有不同组合的 lcm ,我是用DFS预处理的;
参考代码如下:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a)) int a[];
bool vis[];//vis[i]:判断数字 i 是否访问过
bool vis2[*******];//vis2[lcm]:判断当前的lcm是否在之前出现过 int GCD(int a,int b)
{
return a== ? b:GCD(b%a,a);
}
int LCM(int a,int b)
{
return a*b/GCD(a,b);
} void DFS(int t,int lcm,int &k)
{
if(!vis2[lcm])
{
a[k++]=lcm;
vis2[lcm]=true;
} for(int i=;i <= ;++i)
{
if(vis[i])
continue;
vis[i]=true;
DFS(t+,LCM(lcm,i),k);
vis[i]=false;
}
}
int main()
{
int k=; mem(vis,false);
mem(vis2,false); DFS(,,k);
sort(a,a+);
for(int i=;i < k;++i)
printf("%d,",a[i]); return ;
}
预处理出所有的lcm
与处理完后,你会发现最大的lcm为2520,且 2520%(其余的lcm) = 0;
那么,这就好办了,对于当前所形成的数 curNum 和当前的 lcm,我们需要判断 curNum % lcm 是否等于0,那么问题就是
curNum 太大了怎么办?
通过上面的公式,可知 curNum%lcm = curNum%(lcm*(2520/lcm) )%lcm = (curNum%2520)%lcm;
所以,每次只需要将 curNum%2520 即可。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a)) ll n,m;
int digit[];
ll dp[][][];
int a[]={ , , , , , , , , ,,
,,,,,,,,,,
,,,,,,,,,,
,,,,,,,,
,,,,,,,,,}; int GCD(int a,int b)
{
return a== ? b:GCD(b%a,a);
}
int LCM(int a,int b)
{
return a*b/GCD(a,b);
} ll DFS(int curPos,int curNum,int lcm,bool limit)
{
if(curPos == -)
return curNum%lcm == ? :;
int t=lower_bound(a,a+,lcm)-a;
if(!limit && dp[curPos][t][curNum] != -)
return dp[curPos][t][curNum]; int up=limit ? digit[curPos]:;
ll ans=;
for(int i=;i <= up;++i)
ans += DFS(curPos-,(curNum*+i)%,(i != ? LCM(lcm,i):lcm),limit&&i==digit[curPos]);
if(!limit)
dp[curPos][t][curNum]=ans; return ans;
}
ll Solve(ll x)
{
int k=;
while(x)
{
digit[k++]=x%;
x /= ;
}
return DFS(k-,,,true);
}
int main()
{
int test;
scanf("%d",&test);
mem(dp,-);
while(test--)
{
scanf("%lld%lld",&n,&m);
printf("%lld\n",Solve(m)-Solve(n-));
}
return ;
}
CodeForces 55D "Beautiful numbers"(数位DP+离散化处理)的更多相关文章
- codeforces 55D - Beautiful numbers(数位DP+离散化)
D. Beautiful numbers time limit per test 4 seconds memory limit per test 256 megabytes input standar ...
- CodeForces - 55D - Beautiful numbers(数位DP,离散化)
链接: https://vjudge.net/problem/CodeForces-55D 题意: Volodya is an odd boy and his taste is strange as ...
- CodeForces - 55D Beautiful numbers —— 数位DP
题目链接:https://vjudge.net/problem/CodeForces-55D D. Beautiful numbers time limit per test 4 seconds me ...
- Codeforces - 55D Beautiful numbers (数位dp+数论)
题意:求[L,R](1<=L<=R<=9e18)区间中所有能被自己数位上的非零数整除的数的个数 分析:丛数据量可以分析出是用数位dp求解,区间个数可以转化为sum(R)-sum(L- ...
- codeforces 55D. Beautiful numbers 数位dp
题目链接 一个数, 他的所有位上的数都可以被这个数整除, 求出范围内满足条件的数的个数. dp[i][j][k], i表示第i位, j表示前几位的lcm是几, k表示这个数mod2520, 2520是 ...
- FZU2179/Codeforces 55D beautiful number 数位DP
题目大意: 求 1(m)到n直接有多少个数字x满足 x可以整出这个数字的每一位上的数字 思路: 整除每一位.只需要整除每一位的lcm即可 但是数字太大,dp状态怎么表示呢 发现 1~9的LCM 是2 ...
- CF 55D. Beautiful numbers(数位DP)
题目链接 这题,没想出来,根本没想到用最小公倍数来更新,一直想状态压缩,不过余数什么的根本存不下,看的von学长的blog,比着写了写,就是模版改改,不过状态转移构造不出,怎么着,都做不出来. #in ...
- Codeforces 55D. Beautiful numbers(数位DP,离散化)
Codeforces 55D. Beautiful numbers 题意 求[L,R]区间内有多少个数满足:该数能被其每一位数字都整除(如12,24,15等). 思路 一开始以为是数位DP的水题,觉得 ...
- 2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP)
2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 J Beautiful Numbers (数位DP) 链接:https://ac.nowcoder.com/acm/contest/163/ ...
随机推荐
- Java的hashCode和equals方法
当然健壮的代码,两个都重写那是最好. 用不到hashCode的, 也没有必要重写hashCode. 个人感觉. 哈希机制的Java集合类,例如 Hashtable, HashMap, HashSet ...
- java 处理上传exl数据 并导入数据库
思路:处理上传exl表格,并读取文件,数据,讲数据放去集合,循环插入数据库. 重点,读取文件时需要读数据,格式和数据是否正确,(因为只是把整条路打通,所以这块没有细弄): 项目使用ssm框架, str ...
- css的特性
一.继承性: 继承是一种规则,它允许样式不仅应用于某个特定html标签元素,而且应用于其后代. /* 不具有继承性的css样式: */p{border:1px solid red;} 二.特殊性(优先 ...
- class前置声明
https://www.cnblogs.com/King-Gentleman/p/5081159.html 当两个头文件互相包含的时候,类定义会编译出错,这时需要分别添加上对应的类声明 #includ ...
- July 算法习题 - 字符串4(全排列和全组合)
https://segmentfault.com/a/1190000002710424 思想:当前层各节点首元素不同,则各节点的剩余元素也不同:下一层节点交换范围为首元素以外的元素 全排列算法: vo ...
- hdu1839(最小生成树)
题意:字面意思: 思路:就是多了一个前提,有些点之间可能有边,有两个处理方法,一个是有边的,这条边权值归零,另一个是,先一次循环用并查集过一遍: 代码:(用的是第一种方法) #include<i ...
- [西安交大附中集训] d6 删边(cip)
B. 删边(cip.cpp/in/out 1S/256M) 题面 给出一个没有重边和自环的无向图,现在要求删除其中两条边,使得图仍然保持连通. 你的任务是计算有多少组不合法的选边方案.注意方案是无序二 ...
- bzoj2762-[JLOI2011]不等式组
求 \(x=k\) 时满足一元一次不等式 \(ax+b<c\) 的个数. 解出 \(\frac{c-b}{a}\) 之后取整,得到合法区间,用树状数组维护. 注意 \(a\) 的值域是 \([- ...
- 基于junit的单元测试类编写
首先定义抽象类BaseTest package com.geostar.gfstack.operationcenter.common.util; import com.google.gson.Gson ...
- [十]SpringBoot 之 普通类获取Spring容器中的bean
我们知道如果我们要在一个类使用spring提供的bean对象,我们需要把这个类注入到spring容器中,交给spring容器进行管理,但是在实际当中,我们往往会碰到在一个普通的Java类中,想直接使用 ...