[题解] Codeforces Round #708 (Div. 2) C1 题解报告

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 != 0m--

直到 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--

则答案为 mm,和 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;
}
作者:Jude_Zhang
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用BY-NC-SA 许可协议。转载请注明出处!
支持博主:如果您觉得文章对您有帮助,可以点击文章下方赞一下。您的鼓励是博主的最大动力!
原文地址:https://www.cnblogs.com/judezhang/p/14584895.html