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(tn\log n)\) (必定炸裂);因此考虑优化每次询问的时间复杂度

  • \(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 \log n)\)

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);
	}
}
posted @ 2022-12-06 15:22  流浪者海斯t  阅读(100)  评论(0)    收藏  举报