zoj 2562 More Divisors 反素数

思路:

对于任何正整数x,其约数的个数记做g(x).例如g(1)=1,g(6)=4.

 

如果某个正整数x满足:对于任意i(0<i<x),都有g(i)<g(x),则称x为反素数.

 

现在给一个N,求出不超过N的最大的反素数.

 

比如:输入1000 输出 840

 

思维过程:

 

求[1..N]中约数在大的反素数-->求约数最多的数

 

如果求约数的个数 756=2^2*3^3*7^1

 

(2+1)*(3+1)*(1+1)=24

 

基于上述结论,给出算法:按照质因数大小递增顺序搜索每一个质因子,枚举每一个质因子

 

为了剪枝:

 

性质一:一个反素数的质因子必然是从2开始连续的质数.

 

因为最多只需要10个素数构造:2,3,5,7,11,13,17,19,23,29

 

性质二:p=2^t1*3^t2*5^t3*7^t4.....必然t1>=t2>=t3>=....

链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1562

代码如下:

 

 1 #include<iostream>
 2 #include<stdio.h>
 3 #include<algorithm>
 4 #include<iomanip>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<vector>
 8 #define ll long long
 9 #define mod 1000000007
10 using namespace std;
11 int prime[16]={1,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47};
12 ll n,mans,msum;
13 void dfs(ll num,int k,ll sum,ll limit)
14 {
15     if(msum<sum){
16         mans=num;
17         msum=sum;
18     }
19     if(msum==sum&&mans>num) mans=num;
20     if(k>15) return;
21     ll t=num;
22     for(int i=1;i<=limit;i++){
23         if(t*prime[k]>n) break ;
24         t=(ll)t*prime[k];
25         dfs(t,k+1,(ll)sum*(i+1),i);
26     }
27 }
28 int main(){
29     while(scanf("%lld",&n)!=EOF){
30         mans=n;msum=0;
31         dfs(1,1,1,50);
32         printf("%lld\n",mans);
33     }
34     return 0;
35 }
View Code

 

 

 

posted @ 2013-08-28 15:40  _随心所欲_  阅读(236)  评论(0)    收藏  举报