Legend
Link ( extrm{to Codeforces})。
Editorial
考虑分解质因数 (n=prod_{i=0}^{m-1} p_i^{k_i})。
我们不难把某个数字是否分别存在这些质因数状压成二进制数。
去除了 (1) 之后我们的二进制数的值域是 ((0,2^m)) 的开区间。
这容易让人想到格雷码,每次只切换一位,并且去除 (0) 之后相邻两项与一定不为 (0)。
所以如果这题把环改成序列,就可以把所有数字按格雷码顺序来构造答案就行了。
不过是个环,咋办呢?
我的解决办法是把 (U=2^{m}-1) 到末尾的格雷码翻转,这样全集 (U) 被翻到最末尾,一定可以和头部有交。
最末尾的被翻到全集的位置,它和前面的交起来,最高位一定是 1。
除了 (m=2),这样构造都是正确的。我们总能构造出答案为 (0) 的方案。
现在讨论 (m=2) 的情况。
如果 (n=pq),其中 (p,q) 均为质数,那么手动暴力枚举可以知道,答案为 (1)。
否则,质因数为 (U) 的数字至少有 2 个,我们只要构造 (1,cdots,1,3,2,cdots,2,3cdots,3) 这样的序列就行了。
Code
#include <bits/stdc++.h>
#define debug(...) fprintf(stderr ,__VA_ARGS__)
#define __FILE(x)
freopen(#x".in" ,"r" ,stdin);
freopen(#x".out" ,"w" ,stdout)
#define LL long long
const int MX = 1e5 + 23;
const LL MOD = 998244353;
int read(){
char k = getchar(); int x = 0;
while(k < '0' || k > '9') k = getchar();
while(k >= '0' && k <= '9') x = x * 10 + k - '0' ,k = getchar();
return x;
}
std::vector<int> p ,fac[1 << 10] ,code;
int st[MX * 2];
void solve(){
p.clear();
code.clear();
for(int i = 0 ; i < (1 << 10) ; ++i)
fac[i].clear();
std::vector<int> tmp;
int n = read() ,cn;
cn = n;
for(int i = 2 ; i * i <= cn ; ++i){
if(cn % i) continue;
p.push_back(i);
while(cn % i == 0) cn /= i;
}
if(cn != 1) p.push_back(cn);
for(int i = 1 ; i * i <= n ; ++i){
if(n % i == 0){
if(i != 1) tmp.push_back(i);
if(i * i != n) tmp.push_back(n / i);
}
}
for(int j = 0 ; j < (int)tmp.size() ; ++j)
st[j] = 0;
for(int i = 0 ; i < (int)p.size() ; ++i){
for(int j = 0 ; j < (int)tmp.size() ; ++j){
if(tmp[j] % p[i] == 0) st[j] |= 1 << i;
}
}
for(int i = 0 ; i < (int)tmp.size() ; ++i)
fac[st[i]].push_back(tmp[i]);
if(p.size() == 2u){
if(n == p[0] * p[1]){
for(int i = 1 ; i <= 3 ; ++i)
for(auto j : fac[i])
printf("%d " ,j);
puts("
1");
}
else{
for(auto j : fac[1]) printf("%d " ,j);
printf("%d " ,*fac[3].rbegin());
fac[3].pop_back();
for(auto j : fac[2]) printf("%d " ,j);
for(auto j : fac[3]) printf("%d " ,j);
puts("
0");
}
}
else{
int aim = 0;
for(int i = 0 ; i < (int)(1 << p.size()) ; ++i){
code.push_back(i ^ (i >> 1));
if((i ^ (i >> 1)) == (1 << p.size()) - 1){
aim = i;
}
}
std::reverse(code.begin() + aim ,code.begin() + (1 << p.size()));
for(int i = 0 ; i < (int)(1 << p.size()) ; ++i)
for(int j : fac[code[i]])
printf("%d " ,j);
puts("
0");
}
return ;
}
int main(){
int T = read();
while(T--) solve();
return 0;
}