zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    master线程的主循环,后台循环,刷新循环,暂停循环
    InnoDB的后台线程(IO线程,master线程,锁监控线程,错误监控线程)和内存(缓冲池,重做日志缓冲池,额外内存池)
    MySQL的连接方式
    编写高质量的 Java 代码
    TProfiler
    Copy-On-Write容器
    G1 垃圾收集器
    JAVA 虚拟机钩子
    Future和Promise
    算法笔记_134:字符串编辑距离(Java)
  • 原文地址:https://www.cnblogs.com/captain1/p/9873833.html
Copyright © 2011-2022 走看看