CF768div2A-C
一、题目分析
A.Min Max Swap
题意:给你两个数组,你可以操作任意次,a【i】和b【i】交换,要求你求出a数组最大值和b数组最大值相乘的最小值。
你把较大的放入a数组,然后把较小的放入b数组,这样两个数组的最大值相乘一定是最小值。
代码实现:
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline ll read() 5 { 6 ll s = 0,w = 1; 7 char ch = getchar(); 8 while(ch < '0' || ch > '9'){ 9 if(ch == '-') w = -1; 10 ch = getchar(); 11 } 12 while(ch >= '0' && ch <= '9'){ 13 s = (s << 1) + (s << 3) + (ch ^ 48); 14 ch = getchar(); 15 } 16 return s * w; 17 } 18 inline void write(ll x) 19 { 20 if(x < 0) putchar('-'),x = -x; 21 if(x > 9) write(x / 10); 22 putchar(x % 10 + '0'); 23 } 24 int a[10010],b[10010]; 25 int main() 26 { 27 int t,n; 28 cin >> t; 29 while(t--){ 30 int l; 31 cin >> n; 32 for(int i = 1;i <= n;i++) 33 a[i] = read(); 34 for(int i = 1;i <= n;i++) 35 b[i] = read(); 36 for(int i = 1;i <= n;i++) 37 if(b[i] < a[i]) 38 swap(a[i],b[i]); 39 int amax = -1,bmax = -1; 40 for(int i = 1;i <= n;i++){ 41 amax = max(amax,a[i]); 42 bmax = max(bmax,b[i]); 43 } 44 cout << amax * bmax << endl; 45 } 46 }
B.Fun with Even Subarrays
题意:给定你一个序列,每次你可以选择一个l和k(l,k>=1),把a【l】= a【l + k】 a【l + 1】 = a【l + k + 1】....,问这样最少操作多少次可以使这个序列的值全部相等
分析:可以知道我们如果要保证整个序列都相等的话,我们只能从序列的最后往前面复制,但是值得注意的是我们在复制的过程中,已经等于我们最后一个数字的我们可以利用起来,这样就可以最小化 操作次数。
代码实现
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline ll read() 5 { 6 ll s = 0,w = 1; 7 char ch = getchar(); 8 while(ch < '0' || ch > '9'){ 9 if(ch == '-') w = -1; 10 ch = getchar(); 11 } 12 while(ch >= '0' && ch <= '9'){ 13 s = (s << 1) + (s << 3) + (ch ^ 48); 14 ch = getchar(); 15 } 16 return s * w; 17 } 18 inline void write(ll x) 19 { 20 if(x < 0) putchar('-'),x = -x; 21 if(x > 9) write(x / 10); 22 putchar(x % 10 + '0'); 23 } 24 int a[200010]; 25 int main() 26 { 27 int t,n; 28 cin >> t; 29 while(t--){ 30 cin >> n; 31 int ans = 0; 32 for(int i = 1;i <= n;i++) 33 a[i] = read(); 34 for(int i = n;i >= 1;){ 35 if(a[i] == a[n]) 36 i--; 37 else { 38 i -= n - i; 39 ans++; 40 } 41 } 42 cout << ans << endl; 43 } 44 }
C. And Matching
题意:给定一个数n和k(n为2的幂次方,k为0-n-1),问你从0-n-1,中能否有n/2对&(按位与)和为k,如果有,则输出相应的构造方案,没有则输出-1
分析:
第一种情况k = 0,一个数按位与上他的异或数一定为0,比如说2 二进制位010 异或数为101,这样与起来肯定为0
第二种情况k != n-1,我们可以让k与n-1与起来结果肯定还是k,但是我们剩下的要做到和为0,怎么做呢,因为我们拿掉了k,和n-1,那么k的异或没有拿掉,而且n-1的异或也没拿掉,所以让n-1的与k的异或再与一定为0,因为n-1的异或一定是0,所以与任何数与一定是0
第三种情况k == n-1,此时我们可以让n-2与n-1与上,则会出现n-2,那还差1,怎么凑出来呢,我们知道n为偶数,既然n-2被用掉了,那么我们拿n-3试试,n-3肯定是奇数,二进制最后一位肯定是1,那么我们再拿出1来与他相与,则一定为1,那么我们还有0,(n-3)的异或值没用掉,所以让他们相与肯定会得0,其他的全部按照第一种方案构造得0,即可得到和为n-1的n/2的数对。
代码实现
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 inline ll read() 5 { 6 ll s = 0,w = 1; 7 char ch = getchar(); 8 while(ch < '0' || ch > '9'){ 9 if(ch == '-') w = -1; 10 ch = getchar(); 11 } 12 while(ch >= '0' && ch <= '9'){ 13 s = (s << 1) + (s << 3) + (ch ^ 48); 14 ch = getchar(); 15 } 16 return s * w; 17 } 18 inline void write(ll x) 19 { 20 if(x < 0) putchar('-'),x = -x; 21 if(x > 9) write(x / 10); 22 putchar(x % 10 + '0'); 23 } 24 int main() 25 { 26 int t; 27 cin >> t; 28 while(t--){ 29 int n,k; 30 n = read(); 31 k = read(); 32 if(n == 4 && k == 3) 33 cout << -1 << endl; 34 else if(k == 0){ 35 for(int i = 0;i < n / 2;i++) 36 cout << i << ' ' << (i ^ (n - 1)) << endl; 37 } 38 else if(k >= 0 && k < n - 1){ 39 cout << 0 << ' ' << ((n - 1) ^ k) << endl; 40 cout << k << ' ' << n - 1 << endl; 41 for(int i = 1;i < n / 2;i++){ 42 if(i != ((n - 1) ^ k) && i != k) 43 cout << i << ' ' << ((n - 1) ^ i)<< endl; 44 } 45 } 46 else{ 47 cout << 0 << ' ' << 2 << endl; 48 cout << 1 << ' ' << n - 3 << endl; 49 cout << n - 2 << ' ' << n - 1 << endl; 50 for(int i = 3;i < n / 2;i++) 51 cout << i << ' ' << ((n - 1) ^ i) << endl; 52 } 53 } 54 }
本文来自博客园,作者:{scanner},转载请注明原文链接:{https://home.cnblogs.com/u/scannerkk/}

浙公网安备 33010602011771号