cdoj Dividing Numbers 乱搞记忆化搜索
//真tm是乱搞 但是(乱搞的)思想很重要
解:大概就是记忆化搜索,但是原数据范围太大,不可能记下所有的情况的答案,于是我们就在记下小范围内的答案,当dfs落入这个记忆范围后,就不进一步搜索,直接返回记下来的答案,这样就起到了优化的效果,但是并不知道这种复杂度是怎么算的。然而我们由大到小排序,使得状态总可以很快地落入记忆化的范围。
dfs(n,now)代表[1..n]内不会被a[now]...a[k-1]整除的数有多少,那么答案就是dfs(n,0)。
转移关系如下:dfs(n,now)=dfs(n,now+1)-dfs(n/a[i],now+1)
之所以要-dfs(n/a[i],now+1)是为了避免一个数被重复减多次,能被整除的数整除后按大小排列一定是1,2,3,...,n/a[i],如果能被后面的数整除,就将其减去,也就是减dfs(n/a[i],now+1).
/*
某学长的讲解:
假设N比较小,可以这样做。dp[i][j]表示前i个素数,范围在[1,j]里的答案。那么,方程转移dp[i][j]=dp[i-1][j]+dp[i-1][j/p[i]]。(具体为啥仔细想想素数的性质,或者按照分解素数方法来想)
N很大,怎么办。当N<10万,20万,30万可以直接dp做。当N很大的时候,注意到j/p[i],是log级别的,情况数并不会很多。所以可以设一个M,比如M=20万,当j<=M的时候,记忆化,O(1)查询,当j>M的时候,dfs搜索。
这题不好分析复杂度。可以发现,P数组里元素顺序是不影响答案的,我们可以把P从小到大排序,这样j/p[i]中的p[i]会更大,搜索起来更快。(当然,这只是小优化)。
不会写的话看代码。
*/
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#include<map>
#include<stack>
#include<string> using namespace std; const int MAXN=; long long n;
int k;
int a[];
long long f[MAXN][]; bool cmp(int a,int b){
return a>b;
} long long dfs(long long n,int now){
if (now>=k || n==) return n;
if (n<MAXN && f[n][now]>=) return f[n][now];
long long tmp=dfs(n,now+)-dfs(n/a[now],now+);
if (n<MAXN) f[n][now]=tmp;
return tmp;
} int main(){
scanf("%lld%d",&n,&k);
for (int i=;i<MAXN;i++){
for (int j=;j<k;j++){
f[i][j]=-;
}
}
for (int i=;i<k;i++) scanf("%d",&a[i]);
sort(a,a+k,cmp);
printf("%lld\n",dfs(n,)); //printf("I64d printed\n");
return ;
}
/*
20 3
2 3 5 50 2
15 8
*/
cdoj Dividing Numbers 乱搞记忆化搜索的更多相关文章
- CF1028G Guess the Numbers 构造、记忆化搜索
传送门 考虑如果我们当前可以询问\(x\)个数,还剩下\(q\)次询问机会,我们要怎么构造询问方式? 肯定会这么考虑: 找到一个尽可能大的\(P\)满足\([x,P]\)能在每一次能询问\(x\)个数 ...
- Codeforces 374 C. Travelling Salesman and Special Numbers (dfs、记忆化搜索)
题目链接:Travelling Salesman and Special Numbers 题意: 给了一个n×m的图,图里面有'N','I','M','A'四种字符.问图中能构成NIMA这种序列最大个 ...
- POJ 3252 Round Numbers(数位dp&记忆化搜索)
题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于 ...
- 牛客假日团队赛5 F 随机数 BZOJ 1662: [Usaco2006 Nov]Round Numbers 圆环数 (dfs记忆化搜索的数位DP)
链接:https://ac.nowcoder.com/acm/contest/984/F 来源:牛客网 随机数 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 32768K,其他语言6 ...
- UVA 825 Walking on the Safe Side(记忆化搜索)
Walking on the Safe Side Square City is a very easy place for people to walk around. The two-way ...
- tyvj 1004 滑雪 记忆化搜索
滑雪 Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://www.tyvj.cn/p/1004 Description trs喜欢滑雪.他来 ...
- hdu3555 Bomb (记忆化搜索 数位DP)
http://acm.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others) Memory ...
- UVALive 6470 Chomp --记忆化搜索
题意:给一个只有三行的方块阵(横向最多100个),然后p,q,r分别代表第1,2,3层的方格数,两人轮流去掉一个格子,此时这个格子的右上方都会被去掉,面临只剩最左下角的一个格子的状态的人输,问先手能否 ...
- CodeForces 173C Spiral Maximum 记忆化搜索 滚动数组优化
Spiral Maximum 题目连接: http://codeforces.com/problemset/problem/173/C Description Let's consider a k × ...
随机推荐
- class之cls
cls代表的是类本身,一般在静态方法中使用
- SSAS-时间维度的标准设计
1.首先要构建一个时间维度表,下面给出通用的构建时间维度的存储过程: USE [BI_DW] GO /****** Object: StoredProcedure [dbo].[proc_Dim_da ...
- PHP设计模式之装饰器模式
装饰器模式:如果已有对象的部分内容或功能性发生改变,但是不需要修改原始对象的结构或不使用继承,动态的扩展一个对象的功能,则应该使用装饰器模式.简单点说:就是我们不应该去修改已有的类,而是通过创建另外一 ...
- C#调用C++DLL传递结构体数组的终极解决方案
在项目开发时,要调用C++封装的DLL,普通的类型C#上一般都对应,只要用DllImport传入从DLL中引入函数就可以了.但是当传递的是结构体.结构体数组或者结构体指针的时候,就会发现C#上没有类型 ...
- Unix/Linux环境C编程入门教程(22) C/C++如何获取程序的运行时间
1.问:知道程序运行时间我们可以做什么? 在<C++应用程序性能优化>一书中,如果大家读过相信大家一定对性能优化这一块非常上心,文中总是对优化前后的时间对比非常直观给我们一个感受. 那么我 ...
- 动态可视化库Vis.js:社交关系谱
Form Here:http://code.csdn.net/news/2819345 Vis.js 是一个动态的.基于浏览器的可视化库,可处理大量的动态数据并能与这些数据进行交互操作.该项目是由Al ...
- 代码管理git总结
1. http://blog.csdn.net/teresa502/article/details/7388834 pwd 当前工作目录 cd(不加参数) 进root cd(folder) 进入文件夹 ...
- HDU 4122 Alice's mooncake shop
单调队列,裸的!!坑死了,说好的“All the orders are sorted by the time in increasing order. 呢,我就当成严格上升的序列了,于是就各种错.测试 ...
- POJ 3368 RMQ-ST
一直感觉RMQ水,没自己写过,今天写了一道题,算是完全独立写的,这感觉好久没有了... 一直以来,都是为了亚洲赛学算法,出现了几个问题: 1.学的其实只是怎么用算法,对算法的正确性没有好好理解,或者说 ...
- awk(流程控制、内置变量、内置函数、数组)
摘自:http://bbs.51cto.com/thread-883948-1-1.html awk(流程控制.内置变量.内置函数.数组) ... 参考其他的资料,给大家看看.一.awk流程控制语句 ...