zoukankan      html  css  js  c++  java
  • bzoj1225 [HNOI2001] 求正整数

    1225: [HNOI2001] 求正整数

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 762  Solved: 313
    [Submit][Status][Discuss]

    Description

    对于任意输入的正整数n,请编程求出具有n个不同因子的最小正整数m。例如:n=4,则m=6,因为6有4个不同整数因子1,2,3,6;而且是最小的有4个因子的整数。

    Input

    n(1≤n≤50000)

    Output

    m

    Sample Input

    4

    Sample Output

    6
    分析:这道题和反素数这道题非常像.
    涉及到因数个数,可以很容易想到公式(k1 + 1) * (k2 + 1) *......*(kn + 1),那么先把可能的质数给求出来,枚举次数.这道题我们是预先知道了因数的个数,那么枚举的次数就要满足条件:+1后整除因数个数。dfs一下答案就出来了
          但是这样要用到高精度,每一次都高精度很麻烦啊,能不能在中间过程时不用高精度呢?可以的,只要我们在运算的时候取对数就好了.目的就是方便比大小,不用高精度,最后输出的时候用高精度就可以了.
    只涉及到高精度数比大小并且满足对数运算律似乎都可以用对数运算来避免中途高精度运算.我感觉目前只能用到log(xy) = logx + logy和logx^k = k*logx,在搜索的时候分步运算合并即可.
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    #include <cfloat> 
    
    using namespace std;
    
    int n,prime[] = {0,2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53},tot = 16;
    double minn = DBL_MAX,llg[21];
    int res[21],ans[20],p[2000001],len;
    
    void print()
    {
        len = p[1] = 1;
        for (int i = 1; i <= 16; i++)
        {
            for (;ans[i] > 0;ans[i]--)
            {
                for (int j = 1; j <= len; j++)
                p[j] *= prime[i];
                for (int j = 1; j <= len; j++)
                {
                    p[j + 1] += p[j] / 10;
                    p[j] %= 10;
                }
                if (p[len + 1])
                len++;
                while (p[len] / 10 != 0)
                {
                    p[len + 1] += p[len] / 10;
                    p[len] %= 10;
                    len++;
                }
            }
        }
        for (int i = len; i >= 1; i--)
        printf("%d",p[i]);
        printf("
    ");
    }
    
    void dfs(double sum,int cnt,int x)
    {
        if (sum >= minn)
        return; 
        if (cnt == 1)
        {
            minn = sum;
            memset(ans,0,sizeof(ans));
            for (int i = 1; i <= x - 1; i++)
            ans[i] = res[i];
            return;
        }
        if (x > 16)
        return;
        for (int i = 0; (i + 1) * (i + 1) <= cnt; i++)
        if (cnt % (i + 1) == 0)
        {
                res[x] = i;
                dfs(sum + i * llg[x],cnt / (i + 1),x + 1);
            if ((i +1) * (i + 1) != cnt)
            {
                res[x] = cnt / (i + 1) - 1;
                dfs(sum + (cnt / (i + 1) - 1) * llg[x],i + 1,x + 1);
            }
        }
    } 
    
    int main()
    {
        scanf("%d",&n);
        for (int i = 1; i <= 16; i++)
        llg[i] = log(prime[i]);
        dfs(0,n,1);
        print();
        
        return 0;
    }
     
  • 相关阅读:
    [HAOI2012]高速公路(BZOJ2752)
    [SHOI2008]堵塞的交通traffic(BZOJ1018)
    AHOI2009 行星序列Seq (BZOJ1798)
    java注解问题
    回调方法举例
    log4j将日志文件保存到项目中
    ehCache+springMVC的简单实用
    MyBatis排序时使用order by 动态参数时需要注意,用$而不是#
    mybatis配置log4j
    mybatis ---- 分页 (拦截器)
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7464166.html
Copyright © 2011-2022 走看看