题解:P13837 GCD 与 LCM 问题 - 副本

· · 题解

P13837 GCD 与 LCM 问题 题解

问题描述

给定正整数 a,需要找到三个正整数 b, c, d(均不超过 49999),满足:

a + b + c + d = \gcd(a, b) + \operatorname{lcm}(c, d)

解题思路

试将原问题分解为两种情况:

情况一:当 a 为奇数时

假设条件

数学推导

\begin{align*} a + b + c + d &= 1 + c \times d \\ b &= c \times d - c - d - a + 1 \end{align*}

情况二:当 a 为偶数时

假设条件

数学推导

\begin{align*} a + b + c + d &= 1 + \frac{c \times d}{2} \\ b &= 1 + \frac{c \times d}{2} - a - c - d \end{align*}

数学正确性证明

对于奇数 a

\gcd(c, d) = 1 可得 \operatorname{lcm}(c, d) = c \times d,代入原方程:

a + b + c + d = 1 + c \times d

整理得:

b = c \times d - c - d - a + 1

对于偶数 a

\gcd(c, d) = 2 可得 \operatorname{lcm}(c, d) = \displaystyle\frac{c \times d}{2},代入原方程:

a + b + c + d = 1 + \displaystyle\frac{c \times d}{2}

整理得:

b = 1 + \displaystyle\frac{c \times d}{2} - a - c - d

显然,b,c,d \le 49999,因此可以通过。

复杂度分析

算法实现代码

#include <bits/stdc++.h>
using namespace std;
int T, a, b, c, d, x;
int gcd(int x, int y){
    return y == 0 ? x : gcd(y, x % y);
}
int main(){
    scanf("%d", &T);
    while(T--){
        scanf("%d", &a);
        if(a & 1){
            // 奇数情况:从 sqrt(1.1a) 开始枚举
            x = sqrt(1.1 * a);
            if(x == 1) x = 2;
            for(c = x; ; c++){
                d = (a + c) / (c - 1) + 1;
                b = c * d - c - d - a + 1;
                if(gcd(a, b) == 1 && gcd(c, d) == 1){
                    printf("%d %d %d\n", b, c, d);
                    break;
                }
            }
        }
        else{
            // 偶数情况:从 sqrt(2a) 开始枚举偶数
            x = sqrt(a << 1);
            if(x & 1) x++;
            if(x == 2) x = 4;
            for(c = x; ; c += 2){
                d = (a + c) / (c / 2 - 1) + 1;
                if(d & 1) d++;
                b = 1 + c * d / 2 - a - c - d;
                if(gcd(a, b) == 1 && gcd(c, d) == 2){
                    printf("%d %d %d\n", b, c, d);
                    break;
                }
            }
        }
    }
    return 0;
}