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 }
康复训练中~欢迎交流!