BZOJ 1053 - 反素数(搜索)

一个写过的题还搞了半个多小时。。羞耻MAX。。

求反素数的核心思想是“用大的(质数)不如用小的”。一个数的约数个数等于其各质因子的次数加1后的乘积,因此可以从小到大考虑每个质数,枚举其次数,DFS之即可。具体细节详见代码。

 

// BZOJ 1053

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

 typedef long long LL;
 const int prime[16]={2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53}, INF=0x7fffffff;

 #define rep(i,a,b) for (int i=a; i<=b; i++)
 #define read(x) scanf("%d", &x)

 LL ans;
 int n, tot;

 void DFS(int dep, int limit, LL num, int cnt) {  
 // dep为第几个质数,limit为当前最大次数,num为当前的数,cnt为num的约数个数
 	if (dep>16 || num>n) return;
 	if ((num<ans && cnt==tot) || cnt>tot) ans=num, tot=cnt;
 	rep(i,1,limit) {  // 次数直接从1开始搜(注意求反素数的核心思想)
 	    num*=prime[dep];
 	    if (num>n) break;
 	    DFS(dep+1, i, num, cnt*(i+1));
 	}
 }

int main()
{
	read(n);

	ans=INF; tot=1;  // ans为答案,tot为约数个数
	DFS(0,32,1,1);  // 注意数组下标从0开始!
	
	printf("%lld\n", ans);

	return 0;
}


 

posted @ 2015-12-24 19:40  Armeria  阅读(145)  评论(0编辑  收藏  举报