Codeforces 432C

题目链接

题意:

  给出一个长度为n(n<=10^5)的数组a,  数组a是数字1到n的一种排列(打乱顺序).

  每次可以选择两个数(不同)进行交换, 但是交换的条件是被选择的两个数的下标之差加1应该是一个素数.

思路:

  比赛的时候WA到爆..好弱, 思路基本都是对的, 贪心. 用数组pos[i]来维护值i在数组中的位置.

  对于第i个数, 如果 pos[i]-i+1是素数,那么就直接交换.否则, 需要多次交换来使得a[i] = i;

  采用贪心策略, 从i+1开始枚举是否可以与pos[i]进行交换, 这里交换的次数不会很多,

  因为只有当m!+2, m!+3, ......., m!+m时会存在m-1个连续的合数, 而n<=10^5, 所以m <=8

  所以交换的次数不会超过5次.

附上代码:

 1 /*************************************************************************
 2     > File Name: C.cpp
 3     > Author: Stomach_ache
 4     > Mail: sudaweitong@gmail.com
 5     > Created Time: 2014年05月15日 星期四 23时51分15秒
 6     > Propose: 
 7  ************************************************************************/
 8 
 9 #include <cmath>
10 #include <string>
11 #include <cstdio>
12 #include <vector>
13 #include <fstream>
14 #include <cstring>
15 #include <iostream>
16 #include <algorithm>
17 using namespace std;
18 
19 bool is_prime[100005];
20 int a[100005], pos[100005]; // hold the index of the value of i
21 typedef pair<int, int> pii;
22 vector<pii> ans; // keep each move...
23 
24 void 
25 init() {
26       memset(is_prime, true, sizeof(is_prime));
27     is_prime[1] = false;
28     for (int i = 2; i < 1000; i++) {
29           if (is_prime[i]) {
30               for (int j = i*i; j < 100002; j += i) {
31                   is_prime[j] = false;
32             }
33         }
34     }
35     return ;
36 }
37 
38 int
39 main(void) {
40       init();
41       int n;
42     scanf("%d", &n);
43     for (int i = 1; i <= n; i++) {
44           scanf("%d", a + i);
45         pos[a[i]] = i;
46     }
47     for (int i = 1; i <= n; i++) {
48           if (i == a[i]) continue;
49         if (is_prime[pos[i]-i+1]) {
50             swap(a[i], a[pos[i]]);
51             ans.push_back(pii(pos[i], i));
52             pos[a[pos[i]]] = pos[i];
53               pos[i] = i;
54         } else {
55               // distance from index i to pos[i]
56               int d = pos[i] - i;
57             // in other words, a[i] will be equal to i when d equals 0
58             while (d) {
59                   for (int k = d; k >= 1; k--) {
60                       if (is_prime[k+1]) {
61                           // from index of i+d-k to index of pos[i]
62                         swap(a[i+d-k], a[pos[i]]);
63                         // push to ans
64                         ans.push_back(pii(i+d-k, pos[i]));
65                         // update pos[]
66                         pos[a[pos[i]]] = pos[i];
67                         pos[i] = i+d-k;
68                         // update d
69                         d -= k;
70                         break;
71                     }
72                 }
73             }
74         }
75     }
76 //    for (int i = 1; i <= 10; i++) {
77 //          cout << a[i] << ' ';
78 //    }
79 //    cout << endl;
80     int len = ans.size();
81     printf("%d
", len);
82     for (int i = 0; i < len; i++) {
83           if (ans[i].first > ans[i].second) {
84               swap(ans[i].first, ans[i].second);
85         }
86           printf("%d %d
", ans[i].first, ans[i].second);
87     }
88 
89     return 0;
90 }

   

原文地址:https://www.cnblogs.com/Stomach-ache/p/3732799.html