codeforces 768c Jon Snow And His Favourite Number

题意:

给出一个数列,和一种操作,以及两个数x和k。

这个操作有两个步骤:

首先把这个数列按照升序排序,然后把所有奇数位上的数字与x异或。

问执行k次操作之后,这个数列的最大值和最小值是多少。

思路:

由于每个数字异或两次之后会变回本身,所以猜测这个数列有可能会循环,所以就可以暴力计算周期,对于每一次出现的数列,看看是否与前面某次出现过的数列相同,这是暴力的思路。玄学复杂度。

更优雅的思路:

发现a[i]的最大值为1000,任意1000以内的两个数字异或不会超过1023,所以可以统计0到1023当中每个数字出现的次数,然后利用前缀和的思想,计算这个数字在下一次操作中对其他数字出现次数的贡献。

假设这个数字之前有n个数字出现,这个数字的出现次数为y,当前数字为cur,操作后的数列为nex:

1.当n为偶数,y为奇数:

nex[cur^x] += (y/2)+1;nex[cur] += y/2;

2.当n为偶数,y为偶数:

nex[cur^x] += (y/2);nex[cur] += y/2;

3.当n为奇数,y为奇数:

nex[cur^x] += (y/2);nex[cur] += y/2+1;

4.当n为奇数,y为偶数:

nex[cur^x] += (y/2);nex[cur] += y/2;

这个思路的复杂度为O(k*1024)。

思路1代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <string>
 6 #include <map>
 7 using namespace std;
 8 
 9 const int N = 1e5 + 10;
10 int a[N],b[105][N];
11 
12 int judge(int cu,int n)
13 {
14     for (int i = 0;i < cu;i++)
15     {
16         bool f = 0;
17         for (int j = 0;j < n;j++)
18         {
19             if (b[i][j] != b[cu][j])
20             {
21                 f = 1;
22                 break;
23             }
24         }
25         
26         if (!f) return i;
27     }
28     
29     return -1;
30 }
31 
32 int main()
33 {
34     int n,k,x;
35     
36     scanf("%d%d%d",&n,&k,&x);
37     
38     for (int i = 0;i < n;i++) scanf("%d",&a[i]);
39     for (int i = 0;i < n;i++) b[0][i] = a[i];
40     
41     int cnt = 1;
42     int pre = cnt-1;
43     
44     for (;cnt <= k;cnt++)
45     {
46         for (int i = 0;i < n;i++)
47         {
48             b[cnt][i] = b[cnt-1][i];
49         }
50         
51         sort(b[cnt],b[cnt]+n);
52         
53         for (int i = 0;i <= n;i+=2)
54         {
55             b[cnt][i] ^= x;
56         }
57         
58         pre = judge(cnt,n);
59         
60         if (pre != -1) break;
61     }
62     
63     if (cnt >= k)
64     {
65         sort(b[k],b[k]+n);
66         
67         printf("%d %d\n",b[k][n-1],b[k][0]);
68     }
69     else
70     {
71         int ti = cnt - pre;
72         
73         k = (k - pre) % ti; 
74         
75         k += pre;
76         
77         sort(b[k],b[k]+n);
78         
79         printf("%d %d\n",b[k][n-1],b[k][0]);
80     }
81     
82     return 0;
83 }

思路2代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <string>
 6 using namespace std;
 7 const int N = 2000;
 8 
 9 int a[N];
10 int pre[N];
11 int nex[N];
12 
13 int main()
14 {
15     int n,k,x;
16     
17     scanf("%d%d%d",&n,&k,&x);
18     
19     for (int i = 0;i < n;i++)
20     {
21         int y;
22         scanf("%d",&y);
23         a[y]++;
24     } 
25     
26     for (int i = 0;i < k;i++)
27     {
28         memset(nex,0,sizeof(nex));
29         pre[0] = 0;
30         
31         for (int j = 1;j < 1500;j++)
32         {
33             pre[j] = pre[j-1] + a[j-1];
34         }
35         
36         for (int j = 0;j < 1500;j++)
37         {
38             if (a[j])
39             {
40                 if (pre[j] % 2)
41                 {
42                     if (a[j] % 2)
43                     {
44                         nex[j^x] += a[j] / 2;
45                         nex[j] += a[j] / 2 + 1;
46                     }
47                     else
48                     {
49                         nex[j^x] += a[j] / 2;
50                         nex[j] += a[j] / 2;
51                     }
52                 }
53                 else
54                 {
55                     if (a[j] % 2)
56                     {
57                         nex[j^x] += (a[j]/2) + 1;
58                         nex[j] += a[j]/2;
59                     }
60                     else
61                     {
62                         nex[j^x] += a[j]/2;
63                         nex[j] += a[j]/2;
64                     }
65                 }
66             }
67         }
68         
69         for (int j = 0;j < 1500;j++)
70         {
71             a[j] = nex[j];
72         }
73     }
74     
75     int mx,mn;
76     
77     for (int i = 0;i < 1500;i++)
78     {
79         if (a[i])
80         {
81             mn = i;
82             break;
83         }
84     }
85     
86     for (int i = 1500;i >= 0;i--)
87     {
88         if (a[i])
89         {
90             mx = i;
91             break;
92         }
93     }
94     
95     printf("%d %d\n",mx,mn);
96     
97     return 0;
98 }

 

posted @ 2018-04-12 16:51  qrfkickit  阅读(295)  评论(0编辑  收藏  举报