1. 程式人生 > 其它 >CF1765M Minimum LCM 題解

CF1765M Minimum LCM 題解

原題

給出一個整數 \(n\),找出兩個正整數 \(a,b\),使其滿足 \(a+b=n\)\(\operatorname{lcm}(a,b)\) 要儘可能小。

分析

  • 如何求 \(\operatorname{lcm}(a,b)\)

—— \(\operatorname{lcm}(a,b)=a\times b \div \gcd(a,b)\)

—— \(\gcd(a,b)=\gcd(b,a\bmod b)\)

  • 考慮每個詢問 \(O(n)\) 列舉,總時間複雜度為 \(O(tnlogn)\) (必定炸裂);因此考慮優化每次詢問的時間複雜度

  • \(a,b\) 互質,即 \(\gcd(a,b)=1\)

    ,此時 \(\operatorname{lcm}(a,b)=a \times b\),當 \(n\) 不是質數時顯然不是最優選擇,以下給出證明:

\(a=1,b=n-1\) 時,\(\operatorname{lcm}(a,b)=n-1\)

\(a>1,b<n-1\) 時,

\(\operatorname{lcm}(a,b)=ab=a(n-a)\)

要證此時不是最優選擇,只需證:

\(a(n-a)=-a^2+an>n-1\)

只需證:

\(a^2-an+n-1<0\)

整理得:

\((a-1)(a-n+1)=(a-1)(1-b)<0\)

因此,只需列舉 \(n\)

的因數即可,總時間複雜度 \(O(t\sqrt n logn)\)

p.s 記得開longlong,不然會炸~

AC Code

#include<stdio.h>
using namespace std;
typedef long long ll;
int t;
ll gcd(ll x,ll y){return y==0?x:gcd(y,x%y);}
ll min(ll x,ll y){return x<y?x:y;}
int main(){
//	freopen("CF1765M.in","r",stdin);
//	freopen("CF1765M1.out","w",stdout);
	scanf("%d",&t);
	while(t--){
		ll n,ans=1145141919810,ansi;
		scanf("%lld",&n);
		if(n%2==0){//可考慮特判,這個簡單想想就好了
			printf("%lld %lld\n",n/2,n/2);
			continue;
		}
		else if(n%3==0){//這個也可以特判,也很簡單(懶得證了)
			printf("%lld %lld\n",n/3,n/3*2);
			continue;
		}
		for(ll i=1;i*i<=n;i++){//列舉因數
			ll j=n-i;
			if(ans>i*j/gcd(i,j)) ans=1ll*i*j/gcd(i,j),ansi=i;
			if(n%i==0){//如果是因數,考慮更新答案
				ll p=n/i,q=n-p;
				if(q==0) continue;
				if(ans>p*q/gcd(p,q)) ans=1ll*p*q/gcd(p,q),ansi=p;
			}
		}
		printf("%lld %lld\n",ansi,n-ansi);
	}
}