簡體   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