Codeforces Round #647 (Div. 2) - Thanks, Algo Muse! (A-C) (持续补题跟进)
Posted fantadevourer
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Codeforces Round #647 (Div. 2) - Thanks, Algo Muse! (A-C) (持续补题跟进)相关的知识,希望对你有一定的参考价值。
已给出A,B题解,C的代码正确性暂未证明。D,E,F待补。(持续补题...)
------------------------------------------------------------------------------------------------------------------
A. Johnny and Ancient Computer
题意:给你两个数a和b,要求将a通过数次合法操作转换为b,输出最小的操作数,若无法转换为b,则输出-1。合法操作有:乘2、4、8,除以2、4、8。(除以操作只在能被整除的情况下执行)
思路:转换是双向的,所以我们认为问题是怎么由较大数转换为较小数。认为a是较大值,b是较小值,我们可以将问题转化为处理a / b的值。
b⋅t1?⋅t2?…tn?=a
t1?⋅t2?…tn?=a/b?
所以,如果特判a % b != 0必定无法转换,输出-1。然后令k = a / b,用k去试探是否可以被2,4,8整除。由于需要输出最小操作数,所以能被较大数整除就除以较大数。遇到两种情况退出循环:
1、 k == 1,这时说明已经完成了操作,输出操作数即可。
2、 k != 1 && k % 2 == 1,这说明无法操作,输出-1。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<int, int> PII; 7 #define rep(i, x, y) for(i=x;i<=y;i++) 8 #define ref(i, x, y) for(i=x;i>=y;i--) 9 #define MEM(a, x) memset(a, x, sizeof(a)) 10 #define Sca(x) scanf("%d", &x) 11 #define Scl(x) scanf("%lld", &x) 12 #define Scf(x) scanf("%f", &x) 13 #define Sclf(x) scanf("%lf", &x) 14 #define pb push_back 15 #define mp make_pair 16 #define fi first 17 #define se second 18 #define lb lower_bound 19 #define ub upper_bound 20 #define endl ‘ ‘ 21 22 int T, n; 23 bool vis[N]; 24 25 int main() 26 { 27 ios::sync_with_stdio(false); 28 ull a, b; 29 cin >> T; 30 while (T--) { 31 cin >> a >> b; 32 if (a < b) swap(a, b); 33 if (a % b) { 34 cout << - 1 << endl; 35 continue; 36 } 37 ll k = a / b; 38 ll cnt = 0; 39 while (k) { 40 if (k % 8 == 0) { 41 k /= 8; 42 cnt++; 43 }else if (k % 4 == 0) { 44 k /= 4; 45 cnt++; 46 }else if (k % 2 == 0) { 47 k /= 2; 48 cnt++; 49 }else if (k == 1) { 50 break; 51 }else { 52 cnt = -1; 53 break; 54 } 55 } 56 cout << cnt << endl; 57 } 58 return 0; 59 }
总结:比赛时写了ios::sync_with_stdio(false);但是还是用了puts导致wa了两次,拖了些时间。下次注意不能再犯傻了。
B. Johnny and His Hobbies
题意:给出一个集合,要求找到一个值k,使得集合中每一个值ai 变为 ai ^ k,仍使新集合等于原集合。
思路:因为所有n的总和不超过1024,所以我们可以从a[1] ^ a[2...n]枚举k的所有值。确定k值后在[2, n]里对每一个a[i]确定它对应的a[i] ^ k, 二分查找是否存在这个值。答案取最小值。时间复杂度大概是O(n2logn)。(应该没算错吧)
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 2048, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<int, int> PII; 7 #define rep(i, x, y) for(i=x;i<=y;i++) 8 #define ref(i, x, y) for(i=x;i>=y;i--) 9 #define MEM(a, x) memset(a, x, sizeof(a)) 10 #define Sca(x) scanf("%d", &x) 11 #define Scl(x) scanf("%lld", &x) 12 #define Scf(x) scanf("%f", &x) 13 #define Sclf(x) scanf("%lf", &x) 14 #define pb push_back 15 #define mp make_pair 16 #define fi first 17 #define se second 18 #define lb lower_bound 19 #define ub upper_bound 20 #define endl ‘ ‘ 21 22 int T, n; 23 ll a[N]; 24 bool vis[N]; 25 26 int bsearch(int l, int r, ll x) 27 { 28 while (l < r) { 29 int mid = l + r >> 1; 30 if (a[mid] >= x) r = mid; 31 else l = mid + 1; 32 } 33 return l; 34 } 35 36 int main() 37 { 38 ios::sync_with_stdio(false); 39 cin >> T; 40 while (T--) { 41 cin >> n; 42 for (int i = 1; i <= n; i++) 43 cin >> a[i]; 44 if (n % 2) { 45 cout << -1 << endl; 46 continue; 47 } 48 int cnt = 0; 49 ll res = 0x3f3f3f3f; 50 sort(a+1, a+1+n); 51 for (int i = 2; i <= n; i++) { 52 ll ans = a[1] ^ a[i]; 53 cnt = 2; 54 for (int j = 2; j <= n; j++) { 55 if (j == i) continue; 56 ll aim = ans ^ a[j]; 57 int pos = bsearch(1, n, aim); 58 // cout << "j = " << j << " pos = " << pos << endl; 59 if (a[pos] == aim) { 60 cnt ++; 61 }else { 62 break; 63 } 64 } 65 if (cnt == n) { 66 res = min(res, ans); 67 } 68 } 69 if (res == 0x3f3f3f3f) res = -1; 70 cout << res << endl; 71 } 72 return 0; 73 }
总结:拿到题目时就想过枚举k了,不过没敢写,硬是找规律找了好久。。。
C. Johnny and Another Rating Drop
题意:定义了一个不公平值,意味两个数的二进制表示中有多少位不相同。给出一个n,求出0, 1, ... , n中每两个连续的数的不公平值的和。
思路:比赛时我写了前几个值的和,找规律发现答案是2 * n - t,其中t为n和0的不公平值。证明和正解之后慢慢补。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N = 1, M = 1; 4 typedef long long ll; 5 typedef unsigned long long ull; 6 typedef pair<int, int> PII; 7 #define rep(i, x, y) for(i=x;i<=y;i++) 8 #define ref(i, x, y) for(i=x;i>=y;i--) 9 #define MEM(a, x) memset(a, x, sizeof(a)) 10 #define Sca(x) scanf("%d", &x) 11 #define Scl(x) scanf("%lld", &x) 12 #define Scf(x) scanf("%f", &x) 13 #define Sclf(x) scanf("%lf", &x) 14 #define pb push_back 15 #define mp make_pair 16 #define fi first 17 #define se second 18 #define lb lower_bound 19 #define ub upper_bound 20 #define endl ‘ ‘ 21 22 ull T, n; 23 bool vis[N]; 24 25 int main() 26 { 27 ios::sync_with_stdio(false); 28 cin >> T; 29 while (T--) { 30 cin >> n; 31 ll temp = n; 32 ll cnt = 0; 33 while (temp) { 34 if (temp & 1) cnt++; 35 temp >>= 1; 36 } 37 cout << 2ll * n - cnt << endl; 38 } 39 return 0; 40 }
以上是关于Codeforces Round #647 (Div. 2) - Thanks, Algo Muse! (A-C) (持续补题跟进)的主要内容,如果未能解决你的问题,请参考以下文章
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) - Thanks, Algo Muse!
Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)
Codeforces Round #647 (Div. 2) B. Johnny and His Hobbies(枚举)
Codeforces Round #647 (Div. 2) D. Johnny and Contribution(BFS)