zoukankan      html  css  js  c++  java
  • Antiprime数-数论

    题目描述 Description

    如果一个自然数n满足:所有小于它的自然数的约数个数都小于n的约数个数,则称n是一个Antiprime数。譬如:1、2、4、5、12、24都是Antiprime数。

     输入输出格式 Input/output
    输入格式:
    输入文件中只有一个整数n(1≤n≤2 000 000 000)。
    输出格式:
    输出文件中也只包含一个整数,即不大于n的最大Antiprime数。
     输入输出样例 Sample input/output
    样例测试点#1

    输入样例:

    1000
    输出样例:

    840

    思路:

      这个问题可以转化为求n以内约数最多的数,对于一个n,如果它的质因子越小,那么它能分解的因子个数也就越多,而对于有相同因子数的两个数,较小的那个更具有更新的空间,所以当两个数有相同因子数时,我们取较小一个。

      根据唯一分解定理,任何一个大于1的数都可以分解为许多质数的乘积,并且根据质因数的个数可以算出约数的个数,公式为:n=P1x+P2y+P3z+P,这个n的约数个数为(x+1)(y+1)(z+1)(…+1),那么这题,我们可以从1,从小到大循环,每次分解这个数为质因数,最终找到约数最多的数(约数相同取较少的,因为假如取较大的那个,因为较小的那个在前面,并且约数个数和较大的那个一样,这样就会出现较大的数不满足Antiprime数定义,所以我们取较小的数,这样前面就不会有数来和它冲突),输出即可。

      但这样会超时,我们不妨做一下优化,逆用唯一分解定理,从小到大枚举每个质因数的使用个数(由数据范围限定最多枚举到23),搜索答案。

      记住一定要用long long。

    代码如下:

     1 #include<cstdio>  
     2 #include<cmath>    
     3 long long n,maxx,num[12]={0,2,3,5,7,11,13,17,19,21,23},ans;  
     4 void findd(long long now,long long tot,long long u,long long v)//当前累计值,当前累计因数个数,上个质因数使用次数,枚举位置 
     5 {  
     6     if(maxx<tot||(tot==maxx&&ans>now))  
     7     {  
     8         maxx=tot;
     9         ans=now;  
    10     }  
    11     if(v>=11) return;  
    12     for(long long i=1;i<=u;i++)  
    13     {  
    14         now*=num[v];  
    15         if(now>n) return;  
    16         findd(now,tot*(1+i),i,v+1);  
    17     }  
    18 }   
    19 int main()  
    20 {   
    21     scanf("%I64d",&n);  
    22     findd(1,1,500,1);  
    23     printf("%I64d
    ",ans);  
    24     return 0;  
    25 }  
  • 相关阅读:
    1075: 聚餐人数统计
    1074: 百钱买百鸡
    1072: 青蛙爬井
    1073: 级数求和
    1071: 分解质因子
    1070: 小汽车的位置
    1068: 二进制数
    2019 牛客多校 第六场
    2019 牛客多校 第五场
    2019 牛客多校 第二场
  • 原文地址:https://www.cnblogs.com/geek-007/p/6292140.html
Copyright © 2011-2022 走看看