C1. k-LCM (easy version)
简单版本:(k=3)
题目描述
给你一个正整数 (n) 和 (k) ,找出 (k) 个正整数 (a_1,a_2,…,a_k) 。
使得:
-
(a_1+a_2+…+a_k=n)
-
(LCM(a_1, a_2, ldots, a_k) le frac{n}{2})
(注:(LCM) 是 (a_1,a_2,…,a_k) 的最小公倍数)
解题思路
因为 k 恒为 3,所以题目的意思就是找出三个数,和为 n 、三个数的最小公倍数小于 (frac{n}{2}) 。
计算可分为如下步骤:
1、如果 n % 2 = 0 则结果为 ({frac{n}{3}, frac{n}{3}, frac{n}{3}})
2、如果 n % 2 = 0 且 n / 2 % 2 = 0 则结果为 ({frac{n}{2}, frac{n}{4}, frac{n}{4}})
3、以上两条都不满足,则进行暴力枚举:
令 m = n / 2 ,如果 2 * m == n, 则 m--
循环判断如果 m % ( n - m * 2 ) != 0 && ( n - m * 2 ) % m != 0
则 m--
直到 m % ( n - m * 2 ) == 0 || ( n - m * 2 ) % m == 0
输出 ({m, m, n-m*2})
以上三条都能保证三个数中的最大的一个数不超过 (frac{n}{2}) ,且剩余的数都是最大的数的一个倍数,所以最小公倍数一定是这三个数中最小的那个,还能保证三数之和等于 n
。
第三条的意义是:
例如给定一个整数 11
,则 m = 5
,因为 m * 2 = 10 != n
,所以无需 m--
则答案为 m
,m
,和 n - 2 * m
, 现在需要判断这三个数是否成立,因为不知道是 m
大还是 n - 2 * m
大,所以想要判断他们是否是另外一个数的倍数的方法是分别互相取余。
即:m % ( n - m * 2 )
和 ( n - m * 2 ) % m
,如果取余结果为 0
,则答案成立,否则 m
自减1
,再次循环判断。
AC代码
#include <iostream>
#include <cmath>
using namespace std;
void solve ( void )
{
int n, k;
cin >> n >> k;
int m = n / 2;
if ( n % 3 == 0 )
{
int t = n / 3;
cout << t << ' ' << t << ' ' << t << endl;
return;
}
if ( n % 2 == n / 2 % 2 && n % 2 == 0 )
{
cout << n / 2 << ' ' << n / 2 / 2 << ' ' << n / 2 / 2 << endl;
return ;
}
if ( m * 2 == n ) m--;
while ( m % ( n - m * 2 ) != 0 && ( n - m * 2 ) % m != 0 )
m--;
cout << m << ' ' << m << ' ' << n - m * 2 << endl;
}
int main ( void )
{
int T;
cin >> T;
while ( T-- ) solve();
return 0;
}