https://codeforces.com/contest/1933
Codeforces Round 929 div 3
A. Turtle Puzzle:
Rearrange and Negate
绝对值求和即可,一眼题
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 #include <iostream> #include <algorithm> #include <math.h> using namespace std;using ll = long long ;const int N = 1e6 + 100 ;int main () { int t; cin >> t; while (t--) { int n; cin >> n; ll ans=0 ; while (n--) { int x; cin >> x; ans += abs (x); } cout << ans << '\n' ; } return 0 ; }
B. Turtle Math: Fast Three
Task
你可以进行下列两个操作无限次。
1、选择一个数,删掉他,数组总长度-1(没数的时候不能用)
2、选择一个数,加1
问最少多少次操作,可以让数组的和是3的倍数(或者是0,有特殊情况)
本题有两个操作,一个是加1,一个是删除数字,问什么时候可以整除
求个和,如果是3的倍数就不用了,直接输出0
如果是取余为1,记录一下
2也记录一下
如果这个时候和取余为1,很显然我们找到一个取余1的删除即可
如果为2,永远+1,永远1次
剩下的都是2次
总结一下:
如果是0:那么不需要操作就可以得到答案,输出0。
如果是1:最少需要2步,即让某个数加两次1。考虑能不能有更优解,即1步。找到一个数,对3余数为1,存在的话就只需要1步。
如果是2:最少需要1步,操作1和操作2不用想了,反正都是1步。输出1就行
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 #include <iostream> #include <algorithm> #include <math.h> using namespace std;using ll = long long ;const int N = 1e6 + 100 ;int a[N];int main () { int t; cin >> t; while (t--) { int sum = 0 ; int cnt1 = 0 ; int cnt2 = 0 ; int n; cin >> n; for (int i = 1 ; i <= n; i++) { cin >> a[i]; sum += a[i]; if (a[i] % 3 == 1 ) { cnt1++; } else { cnt2++; } } int x = sum % 3 ; if (sum % 3 == 0 ) { cout << 0 <<'\n' ; } else if (x == 1 && cnt1) { cout << 1 << '\n' ; } else if (x == 2 ) { cout << 1 << '\n' ; } else { cout << 2 << '\n' ; } } return 0 ; }
C. Turtle Fingers:
Count the Values of k
(太久没打cf脑子退化了,wa了不知道多少次,才知道是没开longlong)
本题可以暴力
但是折磨我的点是去重
于是用set
将能整除a的倍数都放进去
b也是
然后暴力枚举,再放进去一个集合
并输出最后的大小
从头到尾都保证了本题的正确性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 #include <iostream> #include <algorithm> #include <math.h> #include <set> using namespace std;using ll = long long ;int main () { ios::sync_with_stdio (0 ), cin.tie (0 ), cout.tie (0 ); int t; cin >> t; while (t--) { ll a, b, c; cin >> a >> b >> c; if (c == 1 ) { cout << 1 << '\n' ; } else { ll x = a; ll y = b; set<ll>q; set<ll>p; set<ll>w; q.insert (1ll ); p.insert (1ll ); while (x <= c) { if (c%x==0 ) q.insert (x); x *= a; } while (y <= c) { if (c%y==0 ) p.insert (y); y *= b; } for (set<long long >::iterator i = q.begin (); i != q.end (); i++) { for (set<long long >::iterator j = p.begin (); j != p.end (); j++) { ll sum = (*i) * (*j); if (c % sum == 0 ) { w.insert (c /sum); } } } cout << w.size () << '\n' ; } } return 0 ; }
D. Turtle Tenacity: Continual
Mods
给你一个序列A,选出任意一个排列,要求这个序列连续取模过去最终不等于0。
本题考虑贪心算法
由于是任意的,不需要找到该序列,因此只需要判断是否存在即可
有一条性质:
小的数字对大的数字取模会得到小的数字,因此我们考虑排序
既然是贪心,有时候避免不了会用到排序算法
从小到大排序即可
如果最小值只有一个直接输出Yes,我们已经在123456知道了这样的正确性
否则,如果最小值有多个,康康能不能变出一个更小的数字,
用最后的数字对最小数字取模即可,接下来看代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 #include <iostream> #include <map> #include <algorithm> #include <bits/stdc++.h> using namespace std;const int N = 1e5 + 100 ;map<int , int >a; int b[N];int main () { int t; cin >> t; while (t--) { int n; cin >> n; int minn = 1e9 ; int flag = 0 ; for (int i = 1 ; i <= n; i++) { int x; cin >> x; a[x]++; if (x < minn) { minn = x; } b[i] = x; } sort (b + 1 , b + 1 + n); if (a[minn] == 1 ) { cout << "yes" << '\n' ; } else { for (int i = n; b[i] != minn; i--) { int x = b[i] % minn; if (x != 0 &&x < minn) { cout << "YES" << '\n' ; flag = 1 ; break ; } } } if (!flag && a[minn] != 1 ) { cout << "NO" << '\n' ; } a.clear (); memset (b, 0 , sizeof (b)); } }
E. Turtle vs.
Rabbit Race: Optimal Trainings
lsaac喜欢跑步。
他跑过第一个阶段会得到u的表现分。
他跑过第二个阶段会得到u-1的表现分。
他跑过第三个阶段会得到u-2的表现分。
......
他跑过第k个阶段会得到u+1-k的表现分。
现在有数组a[n],数组中包含阶段数量,如跑过a[1],若a[1]=3,则直接获得3个阶段。
给你数组起始点L,和表现分开头u,问你总表现分最大的情况下,数组结束点R最小是多少。
本题知识点三分
这是一个图,就是本题的图罢
因为本题的单调性是这样的
因为随着我们越来越多,他肯定是先增加后减少的
不像二分,是一直增加,一直减少
我们的目的是找到那个中间的节点
具体我们需要3个判断
l,mid,mid-1
如果mid大于l,但究竟是左边的那种大还是右边的那种大呢,看Mid-1,如果mid-1比mid小,就是左边的大
l要变大
如果是右边就r变小,就这样,可以写代码了
img
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 #include <iostream> #include <map> #include <algorithm> #include <bits/stdc++.h> using namespace std;using ll = long long ;const int N = 1e5 + 100 ;ll a[N]; ll sum[N]; ll h, u; ll qiuhe (int k) { return ((u + (u + 1 - k)) )*k / 2 ; } int main () { int t; cin >> t; while (t--) { int n; cin >> n; for (int i = 1 ; i <= n; i++) { cin >> a[i]; sum[i] = sum[i - 1 ] + a[i]; } int q; cin >> q; while (q--) { cin >> h >> u; int l = h; int r = n; while (l < r) { int mid = (l + r) / 2 ; ll ans_mid = qiuhe (sum[mid] - sum[h - 1 ]); ll ans_l = qiuhe (sum[l] - sum[h - 1 ]); ll ans_hmid=qiuhe (sum[mid - 1 ] - sum[h - 1 ]); if (ans_mid > ans_hmid && ans_mid > ans_l) { l = mid; } else { r = mid; } } if (qiuhe (sum[l + 2 ] - sum[h - 1 ]) > qiuhe (sum[l] - sum[h - 1 ])&&l+2 <=n) { l += 2 ; } else if (qiuhe (sum[l + 1 ] - sum[h - 1 ]) > qiuhe (sum[l] - sum[h - 1 ])&&l+1 <=n) { l += 1 ; } cout << l << ' ' ; } cout << '\n' ; memset (sum, 0 , sizeof sum); } }