对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?
对于任何正整数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的最大的反质数。
【序言】这种20亿的题目,不是数学方法,就是加了很多剪枝的枚举(搜索)。之前思路一直没有,去网上找来的题解都直接贴代码的,要不就是含糊地讲一通。经过认真思考后,总算想出来了。
【分析与思考】什么叫做反质数?设K是反质数,从直观的公式上来看,数K的因数比任何在区间1--K-1中的数i的因数都要多。下面给出我研究出的一个伪定理。
伪定理:如果我们要在N的范围内找最大的反质数,我们只需找到1--N中因数最多的数K就行了。(当然因数相同的情况下找最小的)
一个简短的证明:设K是1--N中因数最大的数。如果满足K<P<=N,且P是反质数,那么P的因数应该比K多。而K已经是1--N中因数最大的数了,与P矛盾。及最大的反质数就是K。
【进一步思考】但怎么找1--N中因数最大的数呢?
有数学公式:K的因数个数=(p1+1)*(p2+1)*------*(pn+1),其中K=a1^p1*a2^p2*------an^pn,且a序列全都是质数。
那么我们可以枚举每个质数来寻找因数最大的质数。
【更深的思考】那么要枚举多少质数呢?因为N<=20亿,而2*3*5*7*11*------*23*29刚好大于N。那么我们最优化枚举K的质数(及其个数)的范围就是2--29。为什么不会再大呢?感性地想一想:同样是质因数,2和3虽然因数个数相同,但2更有发展潜力(呵呵!),所以不存在“K%a2=0,K%a1>0(a1<a2,都是质数)”的情况。
【代码】
#include<stdio.h> using namespace std; int i,n,j; long long ans_num,ans_sum; int prime[11]={0,2,3,5,7,11,13,17,19,23,29}; void dfs(long long sum,long long num,long long now_pri,long long now_sum,long long now_num) { long long newsum=sum*now_sum;if (newsum>n) return; long long newnum=num/now_num*(now_num+1); if (newnum>ans_num) {ans_num=newnum;ans_sum=newsum;} else if (newnum==ans_num&&newsum<ans_sum) ans_sum=newsum; dfs(newsum,newnum,now_pri,now_sum,now_num+1); for (int i=now_pri+1;i<=10;i++) dfs(newsum,newnum,i,prime[i],1); } int main() { scanf("%ld",&n);ans_sum=1; if (n>1) dfs(1,1,1,2,1); printf("%ld",ans_sum); }