簡體   English   中英

如何找到數字中的所有平方(Java)?

[英]How to find all squares in the number (Java)?


我似乎有精神障礙,無法解決以下問題。 基本上,我想找到給定數字中的所有可能的平方,即N = S * S * A,其中給定數字中的N,S * S是平方,而A是其他某個數。 我需要找到所有可能的組合。
到目前為止,我已經將質數序列中的數字N分解,並構建了一個Map,其中鍵是序列中唯一的質數,而值是該質數的出現次數。
例如,對於某些數字,可能會有這樣的順序:
2 2 2 3 3 5 5 5 5 7 7 7 7 7
因此,正方形應為4、9、25、49、36、100、196、225、441、1225。對於這樣的序列,我將具有以下映射:
2 3
3 2
5 4
7 5
接下來,我將奇數值減1:
2 2
3 2
5 4
7 4
主要問題是如何從這張地圖上獲得上面寫的正方形。 我的想法是運行2個循環(不知道效率如何):

for(Map.Entry<BigInteger, Integer> entry : frequency.entrySet()) {
    for(Map.Entry<BigInteger, Integer> ientry : frequency.entrySet()) {
    }
}

很明顯,如何從映射中乘以所有成對的鍵,但是我無法提出必須施加的條件來考慮多重性。
提前非常感謝您!
附言:有沒有嵌套循環的好方法嗎?

我認為嵌套循環不會對您有幫助。 您正在進入遞歸區域。 :-)

您要問的問題基本上可以歸結為這一點。 您有一個數字列表,以及這些數字的頻率。 您想提出所有可以選擇每個號碼一定數量副本的獨特方法。 例如,給定

2 2
3 4
5 2

你想要

2 0 3 0 5 0

2 0 3 0 5 2

2 0 3 2 5 0

2 0 3 2 5 2

2 0 3 4 5 0

2 0 3 4 5 2

2 2 3 0 5 0

2 2 3 0 5 2

2 2 3 2 5 0

2 2 3 2 5 2

2 2 3 4 5 0

2 2 3 4 5 2

如果我們只寫指數,那么我們有

0 0 0
0 0 2
0 2 0
0 2 2
0 4 0
0 4 2
2 0 0
2 0 2
2 2 0
2 2 2
2 4 0
2 4 2

所以問題是如何去生成它。 幸運的是,有一個非常漂亮的遞歸公式可以生成這些數字。 它像這樣。 我們要編寫一個函數AllSquares ,該函數接受一對素數對及其多重性的列表,然后返回可以由完美平方的素數形成的所有可能乘積。 我們將歸納地進行此操作。

作為我們的基本案例,如果您向AllSquares提供空列表,則正好有一個平方乘積,即1,即空列表元素的空積。

對於歸納步​​驟,假設我們有一個非空列表,其第一個元素為(素數,多重性),其余元素為“其余”。 假設我們遞歸地計算通過在列表的其余元素上調用AllSquares形成的列表“組合”。 然后對於i = 0、2、4,...,多重性,如果將列表中的元素乘以基數i ,則將得到一個新的理想平方列表。 如果對所有這些值求和,將最終得到可以由數字形成的所有可能的理想平方。 最酷的一點是,即使多重性是奇數,這也可以工作,因為您只需要考慮偶數指數即可。

這是一些實現此算法的簡單Java代碼。 它根本不是高效的,但是它可以指出要點:

private static List<Integer> allSquares(List<BaseMultiplicity> elems) {
    /* Base case: If the list is empty, there's only one square. */
    if (elems.isEmpty()) {
        return Collections.singletonList(1);
    }

    /* Recursive case: Compute the answer for the rest of the list. */
    List<BaseMultiplicity> rest = new LinkedList<BaseMultiplicity>(elems);
    rest.remove(0);
    List<Integer> recResult = allSquares(rest);

    /* Now, for each even power of this number, add appropriately-scaled
     * copies of the recursive solution to the result.
     */
    List<Integer> result = new ArrayList<Integer>();
    for (int i = 0, base = 1; i < elems.get(0).multiplicity; 
         i += 2, base *= elems.get(0).prime)
        for (Integer elem: recResult)
            result.add(elem * base * base);

    return result;
}

希望這可以幫助!

我要解決的方法是一個組合問題。

  1. 分解並計算主要因素。

  2. 建立一個列表,這樣如果一個因子在原始數字中出現2N2N + 1次,則該因子在此列表中出現N次。 因此,對於2 2 2 2 2 3 3 5的素數,列表將是2 2 3

  3. 構建先前列表的所有組合的列表; 例如{2} {2} {3} {2 2} {2 3} {2 3} {2 2 3}

  4. 將每組中的因子相乘; 例如{2 2 3 4 6 6 12}

  5. 消除重復項以獲取S值列表; 例如{2 3 4 6 12}

現在翻譯成Java。

(構建所有組合的列表可以以迭代或遞歸的方式進行...或通過插入和使用第三方庫來完成。此外,您可以在步驟3中消除重復項;即構建一 唯一的組合。)

對於N = S * S * A計算S的除數並將它們平方。

因此,根據您的映射,您可以將每個指數減半,這可以使S分解。

然后像往常一樣計算與所有指數組合相對應的數字以得到除數。

這是我的功能:

public static NavigableSet<Long> divisors(long n)
{
    NavigableSet<Long> divisors = new TreeSet<Long>();
    divisors.add(1L);
    final Multiset<Long> factorization = primeFactorization(n);
    for (final long primeFactor : factorization.elementSet())
    {
        final int exponent = factorization.getMultiplicity(primeFactor);

        final NavigableSet<Long> newDivisors = new TreeSet<Long>(divisors);
        for (final long d : divisors)
        {
            for (int i = 0; i <= exponent; i++)
            {
                newDivisors.add(d * pow(primeFactor, i));
            }
        }
        divisors = newDivisors;
    }
    return divisors;
}

基本上,多Multiset是從元素到非負整數的映射。

暫無
暫無

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

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