zoukankan      html  css  js  c++  java
  • 【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
  • 相关阅读:
    ZOJ
    ZOJ
    ZOJ
    ZOJ
    HDU
    HDU
    CF 429B B.Working out (四角dp)
    HDU
    ScrollView 里的 EditText 与输入法的用例
    Windows hosts (使用方法 && 不定期更新)
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7989363.html
Copyright © 2011-2022 走看看