计算素因子的数量

时间:2015-05-23 09:21:19

标签: java algorithm prime-factoring

以下是codeforce上的问题
两名士兵在玩游戏。在开始时,他们首先选择一个正整数n并将其交给第二个士兵。然后第二个尝试尽可能多的轮数。每轮包括选择正整数x> 1。如图1所示,n可被x整除并用n / x代替n。当n等于1并且没有更多可能的有效移动时,游戏结束并且第二个士兵的得分等于他执行的回合数。

为了让游戏更有趣,第一个士兵选择n形式! / B!对于某些正整数a和b(a≥b)。这里是k!我们用k表示k的阶乘,它被定义为不大于k的所有正整数的乘积。

第二名士兵的最高分数是多少?

输入 第一行输入由单个整数t(1≤t≤1000 000)组成,表示士兵游戏的数量。

然后按照t行,每行包含一对整数a和b(1≤b≤a≤5000 000),定义游戏的n值。

输出 对于每个游戏输出,第二个士兵可以得到的最高分数。

所以我试图计算n的素因子的数量(如n的素因数分解) 以下是我的代码,但是对于测试用例来说却失败了 a = 5000000且b = 4999995

import java.util.Scanner;
import java.lang.*;

public class Main {

public static void main (String[] args) throws java.lang.Exception
{
    // your code goes here
    int count=0;

    Scanner input=new Scanner(System.in);

    int testcases=input.nextInt();

    for(int m=1;m<=testcases;m++){
        count=0;
        long a=input.nextLong();
        long b=input.nextLong();
        double n=1;

            for(double i=b+1;i<a+1;i++)
                n=n*i;
        //System.out.println(Math.sqrt(n));

            for(int i=2;i<Math.sqrt(n);i++){

                    if(n%i==0){
                        while(n%i==0){
                            n=n/i;

                            count++;
                        }
                    }   
            }

            if(n!=1) count++;

            System.out.println(count);  
    }
  } 
}

3 个答案:

答案 0 :(得分:2)

在你的情况下,一个! / b!是

3,124,993,750,004,374,998,750,000,120,000,000

略大于2 ^ 111。只有最多2 ^ 53的数字才能安全地表示为double值的整数。如果你使用long,你可以将其调高到2 ^ 63,这仍然是不够的。

你必须使用BigInteger或者你必须改变你的方法:而不是分割结果! / b!进入素数因子,划分有助于因子的因子,然后合并素因子集。

用你的例子说明:

5000000 == 2^6 * 5^7
4999999 == 4999999
4999998 == 2 * 3 * 191 * 4363
4999997 == 43 * 116279
4999996 == 2^2 * 1249999

a! / b! == 2^9 * 3 * 5^7 * 43 * 191 * 4363 * 116279 * 1249999 * 4999999

答案 1 :(得分:1)

由于ab的输入很小,我们可以创建一个数组numOfPrime,其索引为ith,

numOfPrime[i] = number of prime factor of i

因此,我们注意到numOfPrime[i] = 1 + numOfPrime[i/x] x是{i}的任何主要因素。

为简单起见,让x成为i的最小素数因子,我们可以使用Sieve of Eratosthenes为每个x预先计算i

int[]x = new int[5000001];
for(int i = 2; i < x.length; i++)
    if(x[i] == 0)
       for(int j = i + i; j < x.length; j+= i)
           if(x[j] == 0)
              x[j] = i;

int[]numOfPrime = new int[5000001];

for(int i = 2; i < x.length; i++)
    if(x[i] == 0)
       numOfPrime[i] = 1;
    else
       numOfPrime[i] = 1 + numOfPrime[i/x[i]];

您可以查看我的submission此问题

答案 2 :(得分:0)

根据@ m-oehm的回答:

int[] factors = new int[a-b];
for(int i=0;i<a-b;i++)
   factors[i] = b+1+i;

boolean done = false;
int i = 2;
while(!done){
   done = true;
   for(int j=0; j<a-b; j++){
      if(i>Math.sqrt(factors[j]) && factors[j]!=1){  // factors[j] is prime
         factors[j] = 1;
         count++;
      }else{
         while(factors[j]%i==0){   // divide factors[j] by i as many times as you can
            factors[j]/=i;
            count++;
         }
      }
      if(factors[j]!=1)            // if all factors have reach 1, you're done
         done = false;
   }
   i++;
}