F. Minimize Fixed Points
F. Minimize Fixed Points
\(\hspace{20px}\)有长度为 \(n\) 的排列 \(p\),如果对所有 \(2 \leq i \leq n\),有 \(\gcd(p_i, i) > 1\),则称其为好排列。在长度为 \(n\) 的所有好排列中,找出一个定点\(^{\text{‡}}\)最少的好排列。如果有多个这样的排列,请打印其中任意一个。
\(\hspace{20px}\)\(^{\text{‡}}\) 排列 \(p\) 的定点是一个索引 \(j\) ( \(1\leq j\leq n\) ),使得 \(p_j = j\) 。
\(\hspace{20px}\)Problem - 2123F - Codeforces
易得出第一个数为 \(1\)。我们可以这么构造数组:分成 \(4\) 组:
我们用一个 \(fa\) 数组存要进行循环的序列,\(d\) 数组存每一个的位置。
Ⅰ质数:\(d[i] = i\)
Ⅱ偶数,但除以二是质数,\(d[i] = i / 2\)
Ⅲ偶数,除以二不是质数,\(d[i] = 2\)
Ⅳ奇数,\(d[i]\) 为第一个质数 \(p\) 使得 \(p | i\)
然后循环时可右移一位,即最后一个第一个输出,其他的从 \(0\) 开始。
点击查看代码
bool isPrime(int n){
if(n < 2) return false;
for(int i = 2;i * i <= n;i++){
if(n % i == 0) return false;
} return true;
}
void solve(){
int n;
cin >> n;
vector<int> a(n + 1);
a[1] = 1;
vector<vector<int>> fa(n + 1);
vector<int> flag(n + 1, -1);
vector<int> d(n + 1);
for(int i = 2;i <= n;i++){
if(isPrime(i)){
fa[i].push_back(i);
d[i] = i;
}else{
if(i % 2 == 0){
if(isPrime(i / 2)){
fa[i / 2].push_back(i);
d[i] = i / 2;
}else{
fa[2].push_back(i);
d[i] = 2;
}
}else{
for(int j = 3;j <= i;j += 2){
if(i % j == 0){
fa[j].push_back(i);
d[i] = j;
break;
}
}
}
}
}
for(int i = 2;i <= n;i++){
//cout << fa[d[i]].size() << " ";
if(flag[d[i]] == -1){
a[i] = fa[d[i]][(int)fa[d[i]].size() - 1];
fa[d[i]].pop_back();
flag[d[i]] = 0;
}else{
a[i] = fa[d[i]][flag[d[i]]];
flag[d[i]]++;
}
}
for(int i = 1;i <= n;i++){
cout << a[i] << " ";
} cout << "\n";
}
浙公网安备 33010602011771号