bzoj 1053 [HAOI2007] 反素数 ant 题解

1053: [HAOI2007]反素数ant

Time Limit: 10 Sec   Memory Limit: 162 MB
Submit: 1134   Solved: 611
[ Submit][ Status]

Description

对于任何正整数x,其约数的个数记作g(x)。例如g(1)=1、g(6)=4。
  如果某个正整数x满足:g(x)>g(i) 0<i<x,则称x为反质数。例如,整数1,2,4,6等都是反质数。
现在给定一个数N,你能求出不超过N的最大的反质数么?

Input

一个数N(1<=N<=2,000,000,000)。

Output

不超过N的最大的反质数。

Sample Input

1000

Sample Output

840

【序言】这种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);
}

你可能感兴趣的:(题解,数学,bzoj)