如何计算强大的数字

时间:2015-12-21 19:01:09

标签: java

我今天遇到了一个相当特殊的Java编码问题,我希望得到一些澄清。

以下是提出的问题:

  

强大的数字是每个素数的正整数m   p除以m,p * p也除以m。

        (a prime number (or a prime) is a natural number that has exactly two (distinct) natural number divisors,
        which are 1 and the prime number itself, the first prime numbers are: 2, 3, 5, 7, 11, 13, ...)

        The first powerful numbers are: 1, 4, 8, 9, 16, 25, 27, 32, 36, ...

        Please implement this method to
        return the count of powerful numbers in the range [from..to] inclusively.

我的问题是究竟是一个多么强大的数字?这是我的定义:

  1. 正整数 AND
  2. 可以被素数整除的正整数 AND
  3. 一个正整数,可以被primeValX * primeValX整除,也可以被primeValX整除
  4. 我的断言错了吗?因为当我将断言应用于我的代码时,它不会返回正确的结果。

    假定的结果应该是1,4,8,9,16

    这是我得到的实际结果:

    i: 4 j: 2 ppdivm: 0 pdivm: 0
    powerful num is: 4
    i: 8 j: 2 ppdivm: 0 pdivm: 0
    powerful num is: 8
    i: 9 j: 3 ppdivm: 0 pdivm: 0
    powerful num is: 9
    i: 12 j: 2 ppdivm: 0 pdivm: 0
    powerful num is: 12
    i: 16 j: 2 ppdivm: 0 pdivm: 0
    powerful num is: 16
    total count: 5
    

    以下是我的代码:

      public static int countPowerfulNumbers(int from, int to) {
                /*
                  A powerful number is a positive integer m that for every prime number p dividing m, p*p also divides m.
    
                  (a prime number (or a prime) is a natural number that has exactly two (distinct) natural number divisors,
                  which are 1 and the prime number itself, the first prime numbers are: 2, 3, 5, 7, 11, 13, ...)
    
                  The first powerful numbers are: 1, 4, 8, 9, 16, 25, 27, 32, 36, ...
    
                  Please implement this method to
                  return the count of powerful numbers in the range [from..to] inclusively.
                 */
               int curCount=0;
               int curPrime;
               int[] rangePrime;
               int pdivm, ppdivm;
               for(int i=from; i<=to; i++){
                   if(i<0){
                       continue;
                   }
    
    
                   rangePrime = primeRange(1 , i);
                   for(int j=0; j<rangePrime.length-1; j++){
    
                       pdivm = i%rangePrime[j];
                       ppdivm = i%(rangePrime[j]*rangePrime[j]);
                       //System.out.println("ppdivm: " + ppdivm + " pdivm: " + pdivm);
    
                       if(pdivm == 0 && ppdivm == 0){
                           curCount++;
                           System.out.println("i: " +i + " j: " + rangePrime[j] + " ppdivm: " + ppdivm + " pdivm: " + pdivm);
    
                           System.out.println("powerful num is: " + i);
                       }
    
                   }
    
    
               }
    
               System.out.println("total count: " + curCount);
               return curCount;
            }
    
           public static int[] primeRange(int from, int to){
    
               List<Integer> resultant = new LinkedList<Integer>();
               for(int i=from; i<=to; i++){
                   if(isPrime(i)== true){
                       resultant.add(i);
                   }
               }
    
               int[] finalResult = new int[resultant.size()];
               for(int i=0; i<resultant.size(); i++){
                   finalResult[i] = resultant.get(i);
    
               }
    
               return finalResult;
           }
    
           public static boolean isPrime(int item){
    
               if(item == 0){
                   return false;
               }
    
               if(item == 1){
                   return false;
               }
    
               Double curInt, curDivisor, curDivi, curFloor;
               for(int i=2; i<item; i++){
                   curInt = new Double(item);
                   //System.out.println(curInt);
                   curDivisor = new Double(i);
                   //System.out.println(curDivisor);
    
                   curDivi = curInt/curDivisor;
                   //System.out.println(curDivi);
    
                   curFloor = Math.floor(curDivi);
    
                   if(curDivi.compareTo(curFloor) == 0){
                       return false;
                   }
               }
    
               return true;
           }
    
        public static void main(String[] args){
    
            System.out.println(isPrime(1));
    
            int[] printout = primeRange(1, 10);
            for(int i=0; i<printout.length; i++){
                System.out.print(" " + printout[i] + " ");
            }
            System.out.println("");
            countPowerfulNumbers(1, 16);
    
            return;
        }
    

    谢谢!

3 个答案:

答案 0 :(得分:1)

根据Wiki article on Powerful Numbers

,您的定义不正确

它表示对于每个素数p除以你的数字,p ^ 2也会除以该数字。

你因此而没有对所有素数的限制除以数字而得到12。所以12可以被2整除,2 ^ 2 = 4。但是,它也可以被3整除,但不能被3 ^ 2 = 9。

答案 1 :(得分:0)

您的定义与引用的定义不符。第1部分是正确的。第2部分和(如Draco18s评论)3不正确。

你的第二点是几乎与第一点重复。奇异的区别在于1是正整数,但它不能被任何素数整除(1本身是not prime,因为你的isPrime()函数正确返回)。

你的第三点开头是(在我看来)条件的尴尬措辞。似乎似乎建议首先检查(i % (p*p)) == 0然后检查(i % p) == 0,这将是多余的,并且允许错过关键情况{{ {1}} (i % (p*p)) != 0,因为第一次检查会导致第二次被跳过。幸运的是,您的代码以正确的((i % p) == 0,然后p)顺序进行检查。

现在我们来到你的第三点的主要错误,即Draco18s和Frank试图指出的错误。您声明强大的数字必须可以被 a primeValX * primeValX和 a primeValX整除。给定的定义规定强大的数字必须可以被primeValX * primeValX整除,以便每个 primeValX可被整除。

有什么区别?您的版本要求p*p primeValX * primeValX可以划分强大的数字。因此,它将排除at least one,因为它不能被任何素数整除,并且包含1等数字,可以被素数122整除。

给定版本要求对于强分数的所有素数,素数的平方也将它们分开。这有两个含义:

  1. 如果没有候选人,默认情况下全部或全部成功。因此,由于2*2的测试没有导致主要除数失败,1是一个强大的数字。
  2. 当您找到一个1p时,您无法使用快捷方式并取得成功。您必须先测试所有素数除数及其正方形 ,然后才能知道 是否为强大的数字。一旦你得到一个其正方形而不是也是一个除数的素数除数,你就可以失败。

答案 2 :(得分:0)

澄清,纠正您的代码,以及更快的方法

您的定义有错误:

2:可被素数整除的正整数=&gt;它是任何非素数的定义

3:一个正整数,可以被primeValX primeValX整除,也可以被primeValX =&gt;整除相当于一个可被primeValX primeValX整除的正整数(它包含断言2)

然后你的定义是&#34;任何带素数除数的素数^ 2&#34;

我拿了原来的定义,你把:

  

强大的数字是每个素数的正整数m   p除以m,p * p也除以m。

像这样:http://mathworld.wolfram.com/PowerfulNumber.html

然后我的算法:如果X * X也是一个dividor,检查你的数字的每个主要数据X.如果没有,它就完成了。

我正确地修改你的代码

for(int i=from; i<=to; i++)
        {
       // CHANGE THERE (or <=3)
        if(i<=1)
           continue;

我放了一面旗帜:

// by default:
boolean powerfull=true;

如果我本身就是素数,那就不强大了!

// if prime: finished !
if (isPrime(i))
    continue;

你的测试中发生了很大的变化:

 // RULE is: i divisor => ixi must be a dividor
 if(pdivm == 0)
       if (ppdivm != 0)
            {
             // You lose !
           System.out.println("i: " +i + " j: " + rangePrime[j] + " ppdivm: " + ppdivm + " pdivm: " + pdivm);
            powerfull=false;
            }

然后,在你的主循环中:

if (powerfull)
    {
    curCount++;
    System.out.println("powerful num is: " + i);
    }

第二种方法,特别是如果你的范围很大,那就更快了:

如我的链接所示:

  

对于a,b&gt; = 1,强大的数字始终为^ 2b ^ 3。

然后:从2到^ ^ 2的循环 另一个从2到^ 1/3的嵌入式循环 并且乘以

像那样:

int from=4;
int to=100000;

Set<Integer> set=new TreeSet<Integer>(); // automatically sorted

// Max candidates
int maxSquarecandidate= (int) Math.sqrt(to);
int maxCubeCandidates=(int) Math.pow(to,1.0/3)+1;

for (int candidate1=1; candidate1<maxSquarecandidate;candidate1++)
    for (int candidate2=1; candidate2<maxCubeCandidates;candidate2++)
        {
        int result=candidate1*candidate1*candidate2*candidate2*candidate2;

        if ((result!=1) && (result>=from) && (result<=to)) set.add(result);
        }

System.out.println(set);
希望它有所帮助!