繁体   English   中英

计算素数

[英]Calculating the number of prime factors

以下是Codeforce上的问题
两名士兵在玩游戏。 首先,他们选择一个正整数n并将其提供给第二个士兵。 然后第二个尝试使最大回合数成为可能。 每个回合包括选择一个正整数x> 1,这样n可以被x整除并用n / x替换n。 当n等于1并且没有更多可能的有效动作时,游戏结束,第二名士兵的得分等于他执行的回合数。

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

第二个士兵的最大可能分数是多少?

输入输入的第一行包含一个整数t(1≤t≤1 000 000),表示士兵玩的游戏次数。

然后跟随t行,每行包含一对整数a和b(1≤b≤a≤5 000 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);  
    }
  } 
}

在您的情况下,一个! / b!

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

比2 ^ 111大一点。 只有最大2 ^ 53的数字才能安全地表示为带double值的整数。 如果使用long ,则可以将其提高到2 ^ 63,但这还不够。

您必须使用BigInteger或必须更改方法:而不是除a的结果! / 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

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

numOfPrime[i] = number of prime factor of i

因此,我们注意到带有x numOfPrime[i] = 1 + numOfPrime[i/x]是i的任意素数。

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

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]];

您可以看看我针对此问题提交的内容

基于@ 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++;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM