题解 CF 1372 B

题目

传送门

题意

给出 \(n\),输出 \(a\) ,\(b\) (\(0 < a \leq b < n\)),使\(a+b=n\)\(\operatorname{lcm}(a,b)\) 最小。

思路

前言


如果你没有到现场,你永远也不会体验到cf 的 OI赛制有多强,评测队列曾超过15min,不得不让此次比赛unrated

但是,我也不知道怎么B、C题提交把语言选成了:C11 ,然后在20分钟后完美地CE 了。

声明

lcm : 最小公倍数

minn : n 的最小质因数

mul : n 的最大 \(\neq n\) 的约数

分析

我们首先找出使 \(\operatorname{lcm}(a,b)\) 最小的 \(a\),\(b\)

\(\because \operatorname{lcm}(a,b)=\frac{a\times b}{\gcd(a,b)}\) ,

\(\therefore\) 我们可以找到 \(n\) 最小的质因数 \(minn\) ,再找到 \(n\) 最大的约数(\(\neq n\)\(mul=\frac{n}{minn}\)

  1. \(n\) 为合数时,我们令答案为 \(mul\) , \((minn-1)\times mul\)

  2. \(n\) 为质数时,我们令答案为 \(1\) , \(n-1\)

输出即可。

正确性

证1

证:\(n\) 为质数, \(k_1=1\) 时 ,\(\operatorname{lcm}(k_1,n-k_1)\) 最小

首先,设 \(k_1 > 0\),\(k_2=n-k_1\),且\(k_1<k_2\)

\(\because\) \(n\) 为质数,\(\gcd(k_1,k_2) = 1\),

\(\therefore\) \(\operatorname{lcm}(k_1,k_2)=k_1\times (n-k_1)\)

\(k_1 = 1\) ,\(\operatorname{lcm}(k_1,k_2)=n-1\)

\(k_1 = 1 + h\)(\(1\leq h\leq \frac{n}{2}\)) ,则

\(\operatorname{lcm}(k_1,k_2)=(1+h)\times (n-1-h) = n - 1 +h \times (n-2-h) > n - 1\)

\(\therefore\)\(n\) 为质数时,\(\operatorname{lcm}(1,n-1)\) 最小。

当然也可以表述为:当 \(n\) 为质数, \(a=1\) 时 ,\(a\times (n-a)\) 最小

类似地,我们也可证明: \(a=1\) 时 ,\(a\times (n-a)\) 最小

我们已经证明了情况2

证2

证:当 \(n\) 为合数, \(k_1=mul\) 时,\(\operatorname{lcm}(k_1,n-k_1)\) 最小

首先,设 \(k_1 > 0\),\(k_2=n-k_1\),且\(k_1<k_2\)\(q = \gcd(k_1,k_2) > 1\)

\(n=g \times q\) , \(k_1=g_1 \times q\)\(k_2 = g_2\times q\) , \(g_1+g_2 =g\)

\(\operatorname{lcm}(k_1,n-k_2)=\frac{k_1 \times (n-k_1)}{q} = g_1\times q \times g_2\)

\(\therefore\)\(g_1=1\) , \(g_1\times g_2\) 最小,

\(\therefore \operatorname{lcm}(k_1,n-k_2)=g_1\times q \times g_2 \geq (g-1)\times q =n - q\) (仅当 \(k_1 = q\) 等号成立)

我们再让 \(q\) 取最大为 \(mul\) 即可让\(\operatorname{lcm}(k_1,n-k_2)\) 最小 ,此时 \(k_1=mul\)

证明完毕(如有漏洞请轻喷)

算法

用线性筛筛出1e5以内素数,方便找答案。

再一个个枚举素数,找到最小的质因子(如果有),判断情况(如果找不到 \(n\) 就肯定是素数),输出答案。

代码

/* 
	* Author :Werner_Yin 
	* Time: 2020-07-11 23:20:15
	* I believe I can AC !
*/ 
#include <bits/stdc++.h>
#define lol long long
#define GDB(x) cout<<"DATA "<<#x<<" :"<<x<<endl; 
#define mes(x) memset(x,0,sizeof(x))
using namespace std;
template <typename T>
void re(T &x){
	#define ge getchar() 
	x = 0;int sgn = 1;char ch = ge;
	for(;!isdigit(ch);ch = ge) if(ch == '-') sgn = -1;
	for(;isdigit(ch);ch = ge) x = (x<<1)+(x<<3)+(ch^48);
	x *= sgn;
}
template <typename T>
void write(T x){
	if(x == 0) putchar(48);
	else if(x < 0) putchar('-');
	int k = 0,que[20];
	while(x > 0){
		que[++k]=x % 10;
		x /= 10;
	}
	for(int i = k;i > 0;i--) putchar(que[i] + 48);
	return;
}
const int MAXN = 1e5 + 10;
int PrimeNum = 0,Prime[MAXN];
bool IsNotPrime[MAXN];
void shai (){
	for(int i = 2;i < MAXN;i++){
		if(!IsNotPrime[i]){
			Prime[PrimeNum++] = i;
		}
		for(int j = 0;j < PrimeNum && Prime[j] * i < MAXN;j++){
			IsNotPrime[Prime[j] * i] = 1;
			if(i % Prime[j])break;
		}
	}
}

int main (){
	shai();
	int T;
	re(T);
	while(T--){
		int n;
		re(n);
		int minn = -1;
		for(int i = 0;i < PrimeNum ;i++){
			if(n % Prime[i] == 0){
				minn = Prime[i];
				break;
			}
		}
		
		int mul = n / minn;
		if(minn == -1||mul == 1) {write(1);write(n-1);}
		else{write ( 1 * mul);write( (minn-1)*mul);}
		putchar('\n');
	}
	return 0;
}
posted @ 2020-07-12 08:47  Werner_Yin  阅读(224)  评论(0编辑  收藏  举报