CF1665A题解

· · 题解

题目大意

t 组数据,每组数据给你一个正整数 n ,让你输出任意一组正整数 abcd ,使得满足 \gcd(a,b) = \operatorname{lcm}(c,d) 并且 a + b + c + d = n

解法

首先特判 n 是否为 4 的倍数,若成立则令 abcd 均为 \frac{n}{4}

证明:

根据最大公约数和最小公倍数的性质: 若 a = b , 则 \gcd(a,b) = a\operatorname{lcm}(a,b) = a

不成立则开始枚举 $a$ , $b$ , $c$ 。 $d$ 可以通过 $n - a - b - c$ 得到,不用进行 $4$ 重循环。 $a$ 从 $\frac{n}{2}$ 开始枚举到 $1$ , $b$ 从 $n - a$ 开始枚举到 $1$ , $c$ 从 $n - a - b$ 开始枚举到 $1$ 。并且枚举 $b$ 时若 $n - a - b < 2$ 进入下一个循环,枚举 $c$ 时若 $n - a - b - c < 1$ 进入下一个循环。 对于上述操作的解释: 因为这道题目的要求是存在解即可输出。所以 $a$ 从 $\frac{n}{2}$ 开始枚举可以保证 $b + c + d$ 一定大于等于 $\frac{n}{2}$ ,同时减少了时间复杂度。 $b$ 与 $c$ 的枚举方式同样减少了时间复杂度。对于 枚举 $b$ 时的特判是因为若 $n - a - b < 2$ 则 $d$ 不成立,枚举 $c$ 时的特判是因为若 $n - a - b - c < 1$ 则 $d$ 不成立。 在枚举出 $a$ , $b$ , $c$ , $d$ 后若满足 $\gcd(a,b) = \operatorname{lcm}(c,d)$ 则输出答案并进入下一组数据。 # 代码 ```cpp #include<iostream> using namespace std; int n,a,b,c,d,t; bool flag = false; int gcd(int x,int y) { return y==0?x:gcd(y,x%y); } int lcm(int x,int y){ return x * y / gcd(x,y); } int main() { cin >> t; while(t--){ cin >> n; if(n%4==0){ a = n/4; b = a; c = b; d = c; cout << a << " " << b << " " << c << " " << d << endl; continue; } flag = false; for(a = n/2;a>=1;a--){ for(b = n - a;b>=1;b--){ if(a+b>n-2){ continue; } for(c = n - a - b;c>=1;c--){ if(n-a-b-c<1){ continue; } d = n - a - b - c; if(gcd(a,b)==lcm(c,d)){ cout << a << " " << b << " " << c << " " << d << endl; flag = true; break; } } if(flag){ break; } } if(flag){ break; } } } return 0; } ```