[英]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;
}
希望這可以幫助!
我要解決的方法是一個組合問題。
分解並計算主要因素。
建立一個列表,這樣如果一個因子在原始數字中出現2N
或2N + 1
次,則該因子在此列表中出現N
次。 因此,對於2 2 2 2 2 3 3 5
的素數,列表將是2 2 3
構建先前列表的所有組合的列表; 例如{2} {2} {3} {2 2} {2 3} {2 3} {2 2 3}
。
將每組中的因子相乘; 例如{2 2 3 4 6 6 12}
。
消除重復項以獲取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.