我今天遇到了一个相当特殊的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,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;
}
谢谢!
答案 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
等数字,可以被素数12
和2
整除。
给定版本要求对于强分数的所有素数,素数的平方也将它们分开。这有两个含义:
2*2
的测试没有导致主要除数失败,1
是一个强大的数字。1
和p
时,您无法使用快捷方式并取得成功。您必须先测试所有素数除数及其正方形 ,然后才能知道 是否为强大的数字。一旦你得到一个其正方形而不是也是一个除数的素数除数,你就可以失败。答案 2 :(得分:0)
澄清,纠正您的代码,以及更快的方法
您的定义有错误:
2:可被素数整除的正整数=&gt;它是任何非素数的定义
3:一个正整数,可以被primeValX primeValX整除,也可以被primeValX =&gt;整除相当于一个可被primeValX primeValX整除的正整数(它包含断言2)
然后你的定义是&#34;任何带素数除数的素数^ 2&#34;
我拿了原来的定义,你把:
像这样:http://mathworld.wolfram.com/PowerfulNumber.html强大的数字是每个素数的正整数m p除以m,p * p也除以m。
然后我的算法:如果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);
希望它有所帮助!