2357 数
题目描述
一个数字被称之为 2357 数,当且仅当其所有大于 1 的因子均能被 2/3/5/7 中的某一个整除。对于数字 N,你需要求出不小于 N 的最小 2357 数。
输入格式
一个数字 N。
输出格式
一个数字表示最小的 2357 数。
样例输入
209
样例输出
210
数据范围和注释
对于 30%的数据,N≤5000。
对于 60%的数据,N≤10^9。
对于 100%的数据,N≤10^13。
【 解析 】
emmm, dfs 万岁!!!
(如果你想不到 dfs ,那或许就该,,,)
然后,,dfs很容易想到加一个【 vis[ ] 数组 】(去重复元素)
然而,dfs数组开不下怎么办? set (去重) 来帮忙!!! (考试的时候并没有想到)
【 考试后 贴出来的题解 】
明显2257数就是质因数分解后,质因数只有2、3、5、7的数,因此直接用这些素数相乘生成符合条件的数,排序,二分找即可。
另外可以使用stl中的set,可降低编程复杂度。-> √
【 关于数据 】
如果你卡空间开 vis 数组,那么最多 90 (看数据 or 人品)或 MLE (计算好,不然就连人品都不看了)
set 的使用 稍后补坑
【 dfs 的可行性 】
根据某dalao的打表,Ta 发现, n = 5千万时 可行的元素只有 2997 个,(这个具体数据是考试后小主打的,)而且越到后面,因为数字很大,即使是×2 都极其大,意味着将跳过很多中间元素,因此 其中的元素 并不会 按 倍数增长,真实情况下 反而 是很慢的,因此 OK !
(真的dalao,学到了啊,考试的时候一个劲的想公式啥的,完全没有发现这一点,直接优化 dfs 即可,
我还是太菜了 - _-)
【 AC代码 】
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#define LL long long
#define inf 0x7f7f7f7f7f7f7f7f
using namespace std;
inline LL wread(){
char c(getchar());LL wans(0),flag(1);
while (c<'0' || c>'9'){if (c=='-') flag=-1;c=getchar ();}
while (c>='0' && c<='9'){wans=wans*10+c-'0';c=getchar();}
return wans*=flag;
}
set <LL> vis;
void init(){
freopen ("2357.in","r",stdin);
freopen ("2357.out","w",stdout);
}
LL n,ans=inf;
void dfs (LL sum){
if (sum>=n) {ans=min(ans,sum); return ;}
if (sum>=ans) return ;
if (vis.count(sum)) return ;
vis.insert(sum);
dfs(sum*2);
dfs(sum*3);
dfs(sum*5);
dfs(sum*7);
}
int main(){
// init();
n=wread();
if (n==1) {puts("2"); return 0;}
dfs(1);
printf("%lld\n",ans);
//可输出其中的可行元素
//printf("%d\n",vis.size());
return 0;
}