• HAOI2007 反素数


    传送门

    这道题或许是披着数论外衣的搜索题……

    在进行爆搜之前,我们有几个结论性的东西需要进行证明。

    1.区间内最大的反质数是因子最多的最小的数。

    这个很好理解,首先它必须因子最多,其次,如果他不是最小的那一个的话,那么它的前面就会有一个因子个数与之相同的数,那他就不是反素数了。

    2.本题数据范围之内,一个数不会有多于10个不同的素因子。

    我们把前11个素数乘起来,已经超出了2*109,所以必然不会有多于10个不同的素因子。

    3.本题数据范围之内,任何一个素因子的指数不超过31.

    这个还是很好理解,毕竟int的最大值我们都懂。

    4.如果一个数是反素数,那么它必然可以被唯一分解为以下形式:x = 2c1 * 3c2 * …… 29cn,满足c单调不增,p必然是前10个素数。

    这个是为什么呢?首先我们先证明后一点,它必然能被分解为最小的几个连续的素数,而且素数不大于29。我们 假设一个素数p是x的一个质因子,那么x / pk * qk,(q是一个小于p的质数),这个数它的因子个数和x是相等的(这个很好证明,数的因子个数计算公式),但是它明显要比x小,说明x不是一个反素数。这样推理出来,那么x必然被分解为连续的几个最小的素数,否则的话,我们就能找到一个数,比它小而因子个数和它一样多。

    其实这个也已经证明了前一点,如果指数出现了递增,我们把增的那个指数减少,前面的增加,这样又得到因子数相同而更小的一个数,他就又不是反素数了。

    有了这么多的限制之后,我们直接爆搜就行。

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    using namespace std;
    typedef long long ll;
    const int M = 20005;
    const int N = 10000005;
    const int INF = 2000000005;
    const int mod = 13;
     
    ll read()
    {
       ll ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9')
       {
          if(ch == '-') op = -1;
          ch = getchar();
       }
       while(ch >='0' && ch <= '9')
       {
          ans *= 10;
          ans += ch - '0';
          ch = getchar();
       }
       return ans * op; 
    }
    
    ll n,p[12] = {2,3,5,7,11,13,17,19,23,29},minn = INF,mtot;
    
    void dfs(ll sum,ll lim,ll cur,ll tot)
    {
       if(cur >= 10)
       {
          if(tot > mtot || !mtot) mtot = tot,minn = sum;
          else if(tot == mtot) minn = min(minn,sum);
          return;
       }
       rep(i,0,lim)
       {
          if(sum > n) break;
          dfs(sum,i,cur + 1,tot * (i + 1));
          sum *= p[cur];
       }
    }
    
    int main()
    {
       n = read();
       if(n == 1) printf("1
    ");
       else dfs(1,31,0,1),printf("%lld
    ",minn);
       return 0;
    }
  • 相关阅读:
    Java Spring AOP用法
    Spring IOC的简单实现
    随机数
    Java 正则表达式
    日期格式转换
    maven settings.xml详解
    JSP与Servlet的关系
    EL表达式学习
    FreeMarker学习2
    FreeMarker学习
  • 原文地址:https://www.cnblogs.com/captain1/p/9873833.html
Copyright © 2020-2023  润新知