题意:给定一个n的排列(n<=100000).定义操作(i,j)为交换a[i]和a[j],i<j,j-i+1为素数.请用不多于5*n次操作将原序列变换为升序.
解法:每次把i和在i位置上的数尝试交换.由哥德巴赫猜想,一个数最多被分为3个质数之和.按照这个进行构造.
#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <algorithm>
#include <string>
#include <map>
#include <iostream>
#include <iomanip>
#include <list>
#include <queue>
using namespace std;
typedef long long ll;
const int N = 100005;
int prime[N] = {0},num_prime = 0;
int isNotPrime[N] = {1, 1};
void produce_prime()
{
for(int i = 2 ; i < N ; i ++)
{
if(! isNotPrime[i])
prime[num_prime ++]=i;
for(int j = 0 ; j < num_prime && i * prime[j] < N ; j ++)
{
isNotPrime[i * prime[j]] = 1;
if( !(i % prime[j] ) )
break;
}
}
}
vector<int> get_even(int v)
{
vector<int> ret;
if (!isNotPrime[v]) {
ret.push_back(v);
return ret;
}
for (int i = 2; ; ++ i) {
if (!isNotPrime[i] && !isNotPrime[v - i]) {
ret.push_back(i);
ret.push_back(v - i);
break;
}
}
return ret;
}
vector<int> get_odd(int v)
{
vector<int> ret;
if (!isNotPrime[v]) {
ret.push_back(v);
return ret;
}
ret.push_back(3);
vector<int> another = get_even(v - 3);
int size = (int)another.size();
for (int i = 0; i < size; ++ i) {
ret.push_back(another[i]);
}
return ret;
}
vector<int> get(int v, int op)
{
if (v % 2 == 1) {
return get_odd(v);
}
vector<int> ret;
if (!op) {
return get_even(v);
}
ret = get_even(v - 2);
ret.push_back(2);
return ret;
}
int a[N], b[N];
vector<pair<int, int> > ans;
void change(int x, int y)
{
swap(b[a[x]], b[a[y]]);
swap(a[x], a[y]);
}
int MAIN()
{
int n;
cin >> n;
for (int i = 1; i <= n; ++ i) {
cin >> a[i];
b[a[i]] = i;
}
produce_prime();
for (int i = 1; i <= n; ++ i) {
if (b[i] == i) continue;
vector<int> r = get(b[i] - i + 1, 0);
if (r.size() == 1) {
ans.push_back(make_pair(i, b[i]));
change(i, b[i]);
continue;
}
r.clear();
r = get(b[i] - i + 2, 0);
if (r.size() == 2) {
int x = b[i] + 1 - r[0];
ans.push_back(make_pair(x, b[i]));
ans.push_back(make_pair(i, x));
change(x, b[i]);
change(i, x);
continue;
}
r.clear();
r = get(b[i] - i + 3, 1);
int x = b[i] + 1 - r[0];
int y = x + 1 - r[1];
ans.push_back(make_pair(x, b[i]));
ans.push_back(make_pair(y, x));
ans.push_back(make_pair(i, y));
change(x, b[i]);
change(y, x);
change(i, y);
}
cout << ans.size() << endl;
int size = (int)ans.size();
for (int i = 0; i < size; ++ i) {
cout << ans[i].first << " " << ans[i].second << endl;
}
return 0;
}
int main()
{
cout << fixed << setprecision(16);
ios :: sync_with_stdio(false);
return MAIN();
}