【BZOJ】1053: [HAOI2007]反素数ant

【题意】记正整数x的因数个数为g(x),当正整数x满足:g(x)>g(i)(0<i<x)时,称x为反素数,求不超过给定N的最大反素数,N<2e9。

【算法】数论,搜索

【题解】

这个问题等价于求1~N中因数最多的最小数字

反素数有以下性质:

1.反素数的素因子一定是从2开始的连续素数

必要性证明:对于A^p1*B^p2,A<C<B,将B更换成C后的数字A^p2*C^p1显然小于原数且因数个数相等,与反素数的定义矛盾。

2.反素数的素因子指数一定按素因子从小到大的顺序不递增

必要性证明:对于A^p1*B^p2(p2>p1),将p1和p2交换后的数字A^p2*B^p1显然小于原数且因数个数相等,与反素数的定义矛盾。

注意:这两条性质不满足充分性

有了这两条性质,就可以搜索素因子指数的所有情况(素因子至多12个,到31为止),找到因数最多的最小数字。

dfs(dep,p,sum,num),第dep个素因子,上一个指数为p,因数个数为sum,数字为num。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const int prime[15]={0,2,3,5,7,11,13,17,19,23,29,31,33,37,41};
int n,mx,ans;
void dfs(int dep,int p,int sum,ll num){
    if(sum>mx||(sum==mx&&num<ans)){
        ans=num;
        mx=sum;
    }
    if(dep>12||num>2e9)return;
    ll s=prime[dep];
    int x=1;
    while(num*s<=n){
        dfs(dep+1,x,sum*(x+1),num*s);
        s*=prime[dep];x++;
    }
}
int main(){
    scanf("%d",&n);
    mx=0;ans=n;
    dfs(1,100,1,1);
    printf("%d",ans);
    return 0;
}
View Code

 

posted @ 2017-12-05 21:01  ONION_CYC  阅读(189)  评论(0编辑  收藏  举报