首页 > 代码库 > codeforces round246 C

codeforces round246 C

像这样的C题对自己来说才是最能提升思维的好题。

首先要知道这些数的组合都是从1-n,

要想对数进行排序,比如pos[i]=4(i位置的数值为4),比较容易能想到i和4直接交换,

题目要求每次交换(i,j)且(j-i+1)为素数,这地方卡住

其实可以利用哥德巴赫猜想(任一大于5的整数都可拆分为三个素数之和,任一大于2的偶数都可拆分为两个素数之和)

然后我们就可以贪心了,先把(j-i+1)拆分,

利用二分找到最接近(j-i+1)的素数然后把对应这个素数上位置的数与pos[i]交换,一直迭代下去。

附个代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>

using namespace std;

#define clr(x) memset(x,0,sizeof(x))
#define fp1 freopen("in.txt","r",stdin)
#define fp2 freopen("out.txt","w",stdout)
#define pb push_back

#define INF 0x3c3c3c3c
typedef long long LL;

typedef pair<int,int> pii;
#define N 100002
int p[N],a[N],b[N];
bool v[N];
vector<pii> ans;
int n,s;

void solve(int i,int j){
  ans.push_back(pii(i,j));
  b[a[i]]=j;
  b[a[j]]=i;
  swap(a[i],a[j]);
}

int main(){

  int s = 0;
  clr(v);
  for(int i = 2;i <= N;i++) if(!v[i]){
    p[s++] = i;
    for(LL j = (LL)i*(LL)i;j <= N;j+=i) v[j] = 1;
  }

  int i, j;
  scanf("%d",&n);
  for (i = 1;i <= n;i++){
    scanf("%d",&a[i]);
    b[a[i]] = i;
  }

  for (i = 1;i <= n;i++){
    while (b[i]!=i){
      if (!v[b[i]-i+1]){
        //printf("%d %d~\n", i, b[i]);
        solve(i,b[i]);
      }
      else {
        j=lower_bound(p,p+s,b[i]-i+1)-p-1;
        //printf("%d %d!\n", b[i]-p[j]+1,b[i]);
        solve(b[i]-p[j]+1,b[i]);
      }
    }
  }

  printf("%d\n",ans.size());
  for (i = 0;i < ans.size();i++)
    printf("%d %d\n",ans[i].first,ans[i].second);
  return 0;
}