试题编号:BZOJ1053
对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。如果某个正整数x满足:g(x)>g(i) 0<i<x
,则称x为反质数。例如,整数1,2,4,6等都是反质数。现在给定一个数N,你能求出不超过N的最大的反质数么
?
输入描述
一个数N(1<=N<=2,000,000,000)。
输出描述
不超过N的最大的反质数。
输入样例
1000
输出样例
840
试题分析
这道题实际上是求1~n中因数最多的数中最小的。(仔细思考,这里不证明)
因为每个数是由几个质数相乘得到的(质数是相乘构成数的最小单位)
所以我们可以用前几个质数(12个就够了)构建反素数。
每个数A=2^p1+3^p2+5^p3……
因数个数cnt=(p1+1)*(p2+1)*(p3+1)*……
我们构建其中因数最多的。因数最多的取最小的。
但是p1,p2,p3等等的数怎么枚举呢?
我们发现,p1,p2,p3是严格不上升的。
证明:假如两个数,a^p1+b^p2,和a^p2+b^p1。a<b,p1>p2。两个数的因数个数相同,但是第一个比较小,所以选择第一个。
代码
不给你看
#include<cstdio>
#include<cstdlib>
#include<cstring>
long long n;
int ss[15]={-1,2,3,5,7,11,13,17,19,23,29,31,37};
long long ans_cnt=0,ans_sum=999999999;
void xfs(int x,long long cnt,long long sum,long long last)
{
if(x>12)return;
if(cnt>ans_cnt || (cnt==ans_cnt && sum<ans_sum))
{
ans_cnt=cnt;
ans_sum=sum;
}
int soy=1;
for(int i=1;i<=last;i++)
{
if(sum*ss[x]>n)break;
sum*=ss[x];
xfs(x+1,cnt*(i+1),sum,i);
}
}
int main()
{
scanf("%I64d",&n);
xfs(1,1,1,100000);
printf("%I64d",ans_sum);
return 0;
}