28行のコードAC——最小合計LCM UVA-10791(最大素因数)

効率よく表現するために、可能な限り少ないコードでインスピレーションを与える


タイトル(送信)リンク-> UVA-10791


題名

正の整数nを入力し、少なくとも2つの数値を見つけ、それらの最小公倍数(最小公倍数)をnにして、最小の合計を出力します。


メンタルジャーニー

最近、私はLanqiaoカップ試験の準備をしていて、この問題を品質要因の分解のトピックに含めました。

午後中ずっと質問を読んだ後、私の脳は騒々しかった。この質問を見たとき、私は質問の意味すら理解できず、ぼんやりと入力し始めた。WA、それからもう一度質問を読み、1時間デバッグして、ACで成功した。

まず最初に、一連の数値a1、a2、a3 ... anがわかっているとします。それらのLCMはnであり、次に、それらが互いに素であるとき、それらが最適解になります。

便宜上、2つの数値を使用して問題を説明します。

aとbのLCMはn、GCDはm、n = a / m * b、それらの合計はsum = a + bです。

mが1でない場合(つまり、aとbが比較的素数でない場合)、それを最適化してaをa = a / mに変更してみませんか?変更後、aとbのLCMはまだnですが、それらの合計は明らかに削減されます

したがって、最も重要なプロパティの1つを取得します。a1、a2、a3 ... anの合計が最小の場合、それらが相互に素数であることを確認する必要があります。相互に素数ではない2つの数値がある限り、さらに最適化できます。

では、どうすればこの2つが相互に素数であることを確認できますか この方法は実際には非常に単純で、素因数を直接分解します

たとえば、24 = 2 2 2 * 3は8と3にしか分解できません。これは3 2があり、これらの3 2は一緒でなければならないためです。これらの3 2が分離している場合、2つの数値が共通になります。素因数は2であり、これら2つの数値のLCMは24ではありません。

別の例は、72 = 2 2 2 3 3です。これは、8と9にしか分割できません。32と2 3は分離できないため、

したがって、nを素因数に分解した後、その方法で処理を行い、素因数を除算しながらそれらを因数として乗算し、処理後、複数の因数を取得します。 2つの比較的重要な特性

その後、さらに分析があります

たとえば、264600 = 8 27 25 * 49の場合、これは3、2、3、3、2、5、2 7の係数であり、処理後に得られる係数であり、8、27、25、49のLCMは264600であり、品質、彼らはまだそれに対処する必要がありますか?必要はありません。それらを追加するだけで、私たちが求めている答えです!どうして?どのように乗算しても、8、27、25、49の数値を乗算できますが、最終的な数値のLCMは引き続きnですが、乗算と加算は直接加算よりも明らかに大きくなります。

この問題の解決策を得ました

1.数値を素因数に分解し、同じ因数を処理された因数として乗算します

2.処理後に得られた複数の要素を直接追加することが答えです

3.タイトルには2つの数値のみが必要であると記載されているため、1と素数に注意する必要があります。素数の場合、分解できるのは因子のみで、因子を1に分解することはできません(因子として1を使用しません)。これらの答えはすべてn + 1です。これは、1とnだけのLCMがnであるためです。


注意:

1. n = 2 ^ 31-1の場合、これは素数であり、結果を出力する場合は+1が必要であり、この大きさはint変数でオーバーフローするため、long longに変更されます
。 1からnへのトラバースは明らかに肥大化しているため、1からsqrt(n)へのトラバースを検討し、最後にnについて特別な判断を下すことができます。


コード表示

#include<bits/stdc++.h> 
using namespace std;

int Prime_Factor(long long n) {
    
    
	long long sum=0; 
	if(n==1) return 1;
	long long num = n/2;	
	for(long long i = 2; i*i <= n; i++)  {
    
    
		if(n%i==0) {
    
    
			long long sum1=1;
			while(n%i==0)  {
    
    
				sum1 *= i; 
				n /= i;
			}
			sum += sum1;
		}
	}
	if(n!=1) sum += n;  	//n等于1代表全除尽了 
	return sum;			
}

int main() {
    
    
	int T=0;
	long long n; while(cin>>n && n) {
    
    
		printf("Case %d: %", ++T);
		long long sum = Prime_Factor(n);
		if(sum==n) sum += 1;
		cout << sum<< endl;
	}
return 0; } 

コメント欄にメッセージを残してください。この記事が役に立った場合は、ブロガーにいいね!みんなのいいねが私の作品の最大のモチベーションです!

おすすめ

転載: blog.csdn.net/weixin_43899069/article/details/108130236