链接:http://codeforces.com/problemset/problem/432/C
任意一个大于2的合数等于两个素数相加,只要知道这个定理就不难了。将每个元素的值作为下标,记录该元素所在的位置,排序的时候判断该点是否为本身,不是得话就去判断两点之间的距离是否为素数,不是变为两个素数相加即可,具体看代码
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
bool prime[maxn],mark[maxn];
int v[maxn];
void Prime()
{
memset(prime,0,sizeof(prime));
memset(mark,0,sizeof(mark));
memset(v,0,sizeof(v));
for(int i=2;i<maxn;i++)
{
if(!mark[i])
{
prime[i]=1;
for(int k=i;k<maxn;k+=i)
mark[k]=1;
}
}
for(int i=2;i<maxn;i++) //小于等于该值最近的素数
if(prime[i]) v[i]=i;
else v[i]=v[i-1];
}
int a[maxn];
map<int,int>m;
vector<pair<int,int> >ve;
int main()
{
int n;
Prime();
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
cin>>a[i];
m[a[i]]=i;
}
for(int i=1;i<=n;i++)
{
while(m[i]!=i)
{
int t=m[i]-i+1;
int p=m[i]-v[t]+1;
ve.push_back(make_pair(p,m[i]));
m[a[p]]=m[i];
swap(a[m[i]],a[p]);
m[i]=p;
// cout<<m[i]<<" "<<m[a[p]]<<endl;
}
}
cout<<ve.size()<<endl;
for(int i=0;i<ve.size();i++)
cout<<ve[i].first<<" "<<ve[i].second<<endl;
return 0;
}