题意:输入一个序列,可以交换两个数直到有序,要求每一次交换的两个数下标只能为素数
题解:贪心,每一个数都有他最后的位置,直接和他最后的位置进行互换就可以,而大于2的数可以分为多个素数相加,那么一次交换可以分解为多个素数的交换
#include <bits/stdc++.h> #define maxn 101000 #define INF 0x3f3f3f3f typedef long long ll; using namespace std; bool isprime[maxn]; int prime[maxn], num, a[maxn], pos[maxn], ans[5*maxn][2], sum, cnt; void doprime(ll n){ num = 0; isprime[1] = 0; memset(isprime, 1, sizeof(isprime)); for(ll i=2;i<=n;i++){ if(isprime[i]){ prime[num++] = i; for(ll j=i*i;j<=n;j+=i) isprime[j] = 0; } } } int main(){ int n; scanf("%d", &n); doprime(maxn); for(int i=1;i<=n;i++){ scanf("%d", &a[i]); pos[a[i]] = i; } for(int i=1;i<=n;i++){ while(pos[i] != i){ for(int j=i;j<pos[i];j++){ if(isprime[pos[i]-j+1]){ ans[cnt][0] = j; ans[cnt++][1] = pos[i]; int t = pos[i]; pos[i] = j; pos[a[j]] = t; swap(a[j], a[t]); break; } } } } printf("%d\n", cnt); for(int i=0;i<cnt;i++){ printf("%d %d\n", ans[i][0], ans[i][1]); } return 0; }