効率よく表現するために、可能な限り少ないコードでインスピレーションを与える
タイトル(送信)リンク-> 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; }
コメント欄にメッセージを残してください。この記事が役に立った場合は、ブロガーにいいね!みんなのいいねが私の作品の最大のモチベーションです!