CF1934E 题解
sunkuangzheng · · 题解
- 给定长度为
n 的序列a ,初始时满足a_i=i 。一次操作为选择三个互不相同的下标i,j,k ,设x=a_i,y=a_j,z=a_k ,令a_i = \operatorname{lcm}(y,z),a_j = \operatorname{lcm}(x,z),a_k = \operatorname{lcm}(x,y) 。- 在
\lfloor \dfrac{n}{6} \rfloor +5 次操作内,将序列a 变成好的。好的序列指的是,对于任意x \in [1,n] ,都存在a 的一个长度至少为2 的子序列a' ,使得\gcd\{a'\} = x 。
对这种 ad-hoc 构造真没一点思路,做法参考了官方题解。
- 性质一:对于三元组
(x,y,z) ,如果满足\gcd(x,y)=\gcd(x,z) = \gcd(y,z)=\gcd(x,y,z) ,则操作一次后序列中将存在\gcd 为x,y,z 的子序列。
不妨令
d = \gcd(x,y,z),x=ad,y=bd,z=cd ,则a,b,c 应当两两互质。那么操作完后,三元组(x,y,z) 将变为(bc \cdot d,ac \cdot d,ab \cdot d) ,两两组成子序列即可得到\gcd 为x,y,z 的子序列。
这样一来,如果我们能把序列
- 性质二:采用上述方法,对于
i \le \dfrac{n}{2} ,我们不需要进行任何操作。
显然序列中一定存在元素
2i 的倍数k \cdot 2i ,那么子序列\{i,k \cdot 2i\} 的\gcd 为i ,已经满足要求。
这样我们的操作次数降到
- 性质三:对于
x \bmod 4 \ge 2 ,[x,x+1,\ldots,x+10,x+11] 这个长度为12 的连续段一定可以拆成4 个满足条件的三元组。
- 对于
x \bmod 4=3 ,(x,x+1,x+2),(x+4,x+5,x+6),(x+8,x+9,x+10) 的结构都是(2k-1,2k,2k+1) ,满足条件。(x+3,x+7,x+11) 的结构是(4k+2,4k+6,4k+10) ,除以2 后变为(2k+1,2k+3,2k+5) ,两个奇数x,y 满足|x-y| \le 4 一定互质,那么(2k+1,2k+3,2k+5) 满足条件。- 对于
x \bmod 4 = 2 ,(x+1,x+2,x+3),(x+5,x+6,x+7),(x+9,x+10,x+11) 的结构是(2k-1,2k,2k+1) ,而(x,x+4,x+8) 的结构是(4k+2,4k+6,4k+10) ,满足要求。
注意到如果
总操作次数
有个细节是当
下面的代码中
/**
* author: sunkuangzheng
* created: 02.03.2024 10:07:11
**/
#include<bits/stdc++.h>
#ifdef DEBUG_LOCAL
#include <mydebug/debug.h>
#endif
using ll = long long;
const int N = 5e5+5;
using namespace std;
int T,n; vector<tuple<int,int,int>> pans[15];
void los(){
cin >> n;
vector<tuple<int,int,int>> ans;
pans[3]={{1,2,3}};
pans[4]={{1,3,4}};
pans[5]={{3,4,5}};
pans[6]={{1,3,5},{2,4,6}};
pans[7]={{2,4,6},{3,5,7}};
pans[8]={{2,6,8},{3,5,7}};
pans[9]={{1,3,5},{2,4,6},{7,8,9}};
pans[10]={{3,4,5},{2,6,8},{7,9,10}};
pans[11]={{2,6,8},{3,5,7},{9,10,11}};
pans[12]={{1,11,12},{6,8,10},{5,7,9}};
auto add = [&](int x,int y,int z){ans.emplace_back(x,y,z);};
if(n <= 12) ans = pans[n];
else{
if(n % 4 == 0 || n % 4 == 3) add(1,n-1,n),n -= 2;
int rn = n / 2;
while(n > rn){
int d = n - 11;
if(d % 4 == 3) add(d,d+1,d+2),add(d+4,d+5,d+6),add(d+8,d+9,d+10),add(d+3,d+7,d+11);
else add(d+1,d+2,d+3),add(d+5,d+6,d+7),add(d+9,d+10,d+11),add(d,d+4,d+8);
n -= 12;
}
}cout << ans.size() << "\n";
for(auto [x,y,z] : ans) cout << x << " " << y << " " << z << "\n";
}int main(){
ios::sync_with_stdio(0),cin.tie(0);
for(cin >> T;T --;) los();
}