题意
找到三个数 a , b , c a,b,c a,b,c, 使其满足 a + b + c = n a+b+c=n a+b+c=n, g c d ( a , b ) = c gcd(a,b)=c gcd(a,b)=c。
思路
由于两个相邻的数必定互质。
所以当
n
n
n 为偶数时,可以使
a
=
(
n
−
1
)
/
2
+
1
,
b
=
(
n
−
1
)
/
2
,
c
=
1
a=(n-1)/2+1, b=(n-1)/2, c=1
a=(n−1)/2+1,b=(n−1)/2,c=1,这样
a
a
a和
b
b
b的最大公约数必定为1 ==
c
c
c,符合题意。
当
n
n
n为奇数时,我们也可以使
c
=
1
c = 1
c=1, 这样我们会得到
a
=
=
b
=
=
(
n
−
1
)
/
2
a==b==(n-1)/2
a==b==(n−1)/2,我们设一个可变的值
x
(
x
=
1
,
2
,
3...
,
n
/
2
−
2
)
x(x=1,2,3...,n/2-2)
x(x=1,2,3...,n/2−2),并使得
a
=
a
+
x
a = a +x
a=a+x,
b
=
b
−
x
b = b - x
b=b−x,当
b
%
(
2
×
x
)
!
=
0
b\%(2\times x) !=0
b%(2×x)!=0时,我们就得到了符合条件的值
a
,
b
,
c
a,b,c
a,b,c,虽然看似
x
x
x会从
1
1
1遍历到
n
/
2
−
2
n/2-2
n/2−2,但实际上只会从
1
1
1遍历到
2
2
2就能得到结果,所以时间复杂度不高。
遍历两次就能得到结果的证明如下:
代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
int main(){
int n;cin>>n;
while(n--){
ll x;cin>>x;
if(x%2 == 0) cout<<(x-1)/2+1<<" "<<(x-1)/2<<" "<<1<<endl;
else{
int t = (x-1) / 2;
int a = t, b = t;
for(int i = 1; i; i ++){
a ++;b --;
if(b % (2*i) != 0) break;
}
cout<<a << " " << b <<" " << 1 <<endl;
}
}
return 0;
}