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);
}
}
浙公网安备 33010602011771号