簡體   English   中英

出於數學目的使用循環進行編程。 (Java)

[英]Program using loops for math purpose. (Java)

讓我解釋一下這個問題。

我需要編寫一個程序,在其中輸入數字N,然后必須找到可被所有數字整除為1的最小數字。

例如:。 如果我的N為5,則答案為60。60被5、4、3、2和1整除。

這是我到目前為止所擁有的...

import java.util.Scanner;

public class Questão_04 {
public static void main (String [] args)
{
    int x = 1, n = 1, d = x % n;

    System.out.print("Enter N: ");

    Scanner in = new Scanner(System.in);

    n = in.nextInt();

    do
    {
        if (d != 0)
        {
            x = x + 1;
            do
            {
                n = n -1;                   
            } while (n != 0);
        }
        else
        {
            do
            {
                n = n - 1;
            } while (d != 0);
        }

    } while (n != 0);

    System.out.print(x);\\the minimum number divisible by N and all up to N.

} 

終於,經過一段時間的努力,我終於找到了一個有效的解決方案:

public int smallestMatching(int n){
    ArrayList<Integer> divisors = new ArrayList<>();

    for(int i = 2 ; i <= n ; i++){
        int tmp = i;

        //simplify div, until it can't be created by multiplying elements of divisors
        for(int div : divisors)
            if(tmp % div == 0)
                tmp /= div;

        if(tmp != 1) 
        //tmp cant be generated from number that are content of divisors
        //-> add to divisors
        {
            divisors.add(tmp);
        }
    }

    //calculate the final result
    int result = 1;
    for(int div: divisors)
        result *= div;

    return result;
}

喜歡這個問題:D。

查找此值的有效算法僅考慮小於或等於N的素數。

  • v = 1開始
  • 對於素數小於或等於N p_i
    • 找出最大整數q_i使得p_i ^ q_i <= N
    • v *= p_i ^ q_i

對於您的示例N = 5,素數為2,3,5和

  • 2 ^ 2 = 4 <5 <2 ^ 3
  • 3 ^ 1 = 3 <5 <3 ^ 3
  • 5 ^ 1 = 5 = 5 <5 ^ 2

所以v = 2 ^ 2 * 3 * 5 = 60

對於N = 18,您最終得到

v = 2 ^ 4 * 3 ^ 2 * 5 * 7 * 11 * 13 * 17

唯一棘手的問題是生成小於N的素數。

但是,由於v隨着N的增加而快速增長( O(N!)O(N^log(N))或類似的東西),您將在N的某個較低值(在幾百個?)這意味着您可能可以避免預先計算一張小的素數表。 (除非您使用任意精度數字類型)

我猜您正在嘗試計算f(n) = lcm(1,2,...,n) 我認為該函數似乎在n較小時迅速增長,盡管隨着質數空間的逐漸縮小,它最終可能會逐漸減小。 理論上說ln f(n)/n漸近於1 ,因此f(n)大致呈指數增長。

我們可以通過注意lcm(1,2,...,n) = lcm(lcm(1,2,...,n-1),n)來簡化,因此f(n)可以遞歸計算。 此外, lcm(a,b) = a*b/gcd(a,b)因此我們可以根據標准gcd函數編寫遞歸。 我建議遞歸計算f如下: f(n+1) = f(n) / gcd(f(n),n+1) * (n+1) 在相乘之前進行除法可減小中間結果的大小。 gcd均分f(n)因此整數除法很好。 您可以記住f(n)來加快計算速度,盡管如果僅計算一個n f(n)不會有幫助。

我已經在下面的Java中實現了該功能。 它以我能達到的速度運行,至少直到堆棧大小溢出為止,在我的計算機上大約為n=10000 您可以重組以使用迭代代替遞歸,這可能會使最大值n更高。 (基於類似的情況,我猜想它在計算機上的n=50000左右會用完內存,但是我實際上沒有嘗試過。)

import java.math.BigInteger;

public class LCM {
  public static BigInteger f(int n) {
    if (n == 1) return BigInteger.ONE;
    BigInteger prev = f(n-1);
    return prev.divide(prev.gcd(BigInteger.valueOf(n)))
      .multiply(BigInteger.valueOf(n));
  }

  public static void main(String[] args) {
    int n = Integer.parseInt(args[0]);
    System.out.println("f(" + n + ") = " + f(n));
  }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM