【 NOIP 模拟考 】【 TEST 7 】【 T1 2357 数 】

                                                       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;
}

猜你喜欢

转载自blog.csdn.net/violinlove/article/details/81357906