Java中获取一个数字的因子数量的最快方法是什么
我正在尝试用Java编写一个函数,它将返回一个特定数字的因子数 应考虑以下限制Java中获取一个数字的因子数量的最快方法是什么,java,algorithm,math,Java,Algorithm,Math,我正在尝试用Java编写一个函数,它将返回一个特定数字的因子数 应考虑以下限制 它应该用biginger完成 不允许存储以前生成的数字,因此处理更多,内存更少。(您不能像中那样使用“Atkin筛选”) 负数可以忽略 这是我到目前为止所做的,但是速度非常慢 public static int getNumberOfFactors(BigInteger number) { // If the number is 1 int numberOfFactors = 1; if (
public static int getNumberOfFactors(BigInteger number) {
// If the number is 1
int numberOfFactors = 1;
if (number.compareTo(BigInteger.ONE) <= 0) {
return numberOfFactors;
}
BigInteger boundry = number.divide(new BigInteger("2"));
BigInteger counter = new BigInteger("2");
while (counter.compareTo(boundry) <= 0) {
if (number.mod(counter).compareTo(BigInteger.ZERO) == 0) {
numberOfFactors++;
}
counter = counter.add(BigInteger.ONE);
}
// For the number it self
numberOfFactors++;
return numberOfFactors;
}
public static int getNumberOfFactors(BigInteger数字){
//如果数字是1
int numberOfFactors=1;
如果(number.compareTo(biginger.ONE)我可以提出更快的解决方案,尽管我感觉它还不够快。您的解决方案在O(n)
中运行,而我的解决方案将在O(sqrt(n))中运行。
我将使用这样一个事实,如果n=xi1p1*xi2p2*xi3p3*…xikpk是n
(即xij都是不同的素数)的素因子分解,那么n总共有(p1+1)*(p2+1)*…*(pk+1)因子
现在,解决方案是:
BigInteger x = new BigInteger("2");
long totalFactors = 1;
while (x.multiply(x).compareTo(number) <= 0) {
int power = 0;
while (number.mod(x).equals(BigInteger.ZERO)) {
power++;
number = number.divide(x);
}
totalFactors *= (power + 1);
x = x.add(BigInteger.ONE);
}
if (!number.equals(BigInteger.ONE)) {
totalFactors *= 2;
}
System.out.println("The total number of factors is: " + totalFactors);
BigInteger x=新的BigInteger(“2”);
长期总因子=1;
而(x.multiply(x).compareTo(number)则有一些改进:
您只需要检查sqrt(n),而不是n/2。这使得您的算法是O(sqrt(n))而不是O(n)
您只需在检查2后检查奇数,这将使速度加倍
虽然您不能使用前面的数字,但您可以使用已知的素数和少量存储构建一个筛子:2,3是素数,因此只需检查(例如)11,13,17,19,23,而不是12,14,15,16,18。因此,您可以存储3:[+2,+4]的增量模式,每6次重复一次:
var delta=[2,4];
var周期=6;
var=3;
var i=0;
而Boris Strandjev提出的(val最快的解决方案在Java中生成大量输出时存在一些问题。
这是Java中查找大整数除数的最快算法
以下是我将成功运行的代码:
import java.math.BigInteger;
import java.util.Scanner;
class ProductDivisors {
public static BigInteger modulo=new BigInteger("1000000007");
public static BigInteger solve=new BigInteger("1");
public static BigInteger two=new BigInteger("2");
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
BigInteger prod=new BigInteger("1");
while(N-->0){
prod=sc.nextBigInteger();
solve=solve.multiply(prod);
}
BigInteger x = new BigInteger("2");
BigInteger total = new BigInteger("0");
BigInteger totalFactors =new BigInteger("1");
while (x.multiply(x).compareTo(solve) <= 0) {
int power = 0;
while (solve.mod(x).equals(BigInteger.ZERO)) {
power++;
solve = solve.divide(x);
}
total = new BigInteger(""+(power + 1));
totalFactors=totalFactors.multiply(total);
x = x.add(BigInteger.ONE);
}
if (!(solve.equals(BigInteger.ONE))) {
totalFactors =totalFactors.multiply(two);
}
totalFactors=totalFactors.mod(modulo);
System.out.println(totalFactors);
}
}
import java.math.biginger;
导入java.util.Scanner;
类乘积因子{
公共静态BigInteger模=新的BigInteger(“100000007”);
公共静态BigInteger solve=新的BigInteger(“1”);
公共静态BigInteger 2=新的BigInteger(“2”);
公共静态void main(字符串[]args){
//TODO自动生成的方法存根
扫描仪sc=新的扫描仪(System.in);
int N=sc.nextInt();
BigInteger产品=新的BigInteger(“1”);
而(N-->0){
prod=sc.nextbiginger();
求解=求解。乘法(prod);
}
BigInteger x=新的BigInteger(“2”);
BigInteger总计=新的BigInteger(“0”);
BigInteger totalFactors=新的BigInteger(“1”);
while(x.multiply(x).compareTo(solve)如果存在重复的因子,例如2*2*2将返回2(1代表2,1代表4),则此操作也会失败@PeterLawrey不是真的-他迭代所有因子,从不进行除法运算。因子分解可能非常慢,以至于在某些密码算法中使用。它被称为,9000是对的,这不是一个容易的问题。@PeterLawrey问题从来没有说它应该只返回素数因子的数目。从问题的措辞来看,我假设8的因子数应该返回4(1,2,4,8)相当快?该代码在您的计算机上运行多长时间10000007^2
我把它减少到22。也许你是对的,在极端情况下,它没有我声称的那么快,但我想不出更好的解决方案。@Betlista btw用long替换所有大整数将时间减少到3秒。遗憾的是,biginger
在这里有很大的限制。要稍微加快速度,请添加一个fi第一次,然后再加上两个。例如2,3,5,7…。这将使运行时间减半。看起来这将返回4对9…你不是把平方根作为一个因子计算两次吗?我认为你的代码至少在n=9或n=49时工作不好。关于周期的想法可能是“跳过以0,2,4,5,6,8中的一个结尾的数字”,所以delta是4,2,2,2,从3开始-检查10个数字中的4…9可以被3整除,所以检查3应该在循环之外进行。49可以被7整除,7在第一次迭代中被选为3的+4 delta。49在第八次迭代中也会被+4 delta击中。delta[0]是2,所以您正在检查5,9,11,15。。。(跳过素数7和13)如果存在val
条件,如何命中49?缺少计数的初始化,但我猜是2@Betlista:谢谢您的检查,我没有在列表末尾添加正确的内容。我应该添加6-4(最终的增量),而不是添加6。这样您可以得到5,7,11,13,17,19
import java.math.BigInteger;
import java.util.Scanner;
class ProductDivisors {
public static BigInteger modulo=new BigInteger("1000000007");
public static BigInteger solve=new BigInteger("1");
public static BigInteger two=new BigInteger("2");
public static void main(String[] args) {
// TODO Auto-generated method stub
Scanner sc=new Scanner(System.in);
int N=sc.nextInt();
BigInteger prod=new BigInteger("1");
while(N-->0){
prod=sc.nextBigInteger();
solve=solve.multiply(prod);
}
BigInteger x = new BigInteger("2");
BigInteger total = new BigInteger("0");
BigInteger totalFactors =new BigInteger("1");
while (x.multiply(x).compareTo(solve) <= 0) {
int power = 0;
while (solve.mod(x).equals(BigInteger.ZERO)) {
power++;
solve = solve.divide(x);
}
total = new BigInteger(""+(power + 1));
totalFactors=totalFactors.multiply(total);
x = x.add(BigInteger.ONE);
}
if (!(solve.equals(BigInteger.ONE))) {
totalFactors =totalFactors.multiply(two);
}
totalFactors=totalFactors.mod(modulo);
System.out.println(totalFactors);
}
}