Codeforces Global Round 27
写在前面
比赛地址:https://codeforces.com/contest/2035。
前期犯唐 C 不会呃呃,后面 E 会了然而跑去写什么狗屁三分似掉了也没救回来。
本来想着一场上橙的,这下又掉分了哈哈。
厌学中。
A 签到
发现受到影响的位置仅有三种:
- 在第 行, 列的,左移一位;
- 在第 行,第 1 列的,移动到上一行最后;
- 在第 行,第 列的,左移一位。
三种位置的贡献求和即可。
复制复制// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long //============================================================= //============================================================= //============================================================= int main() { //freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { int n, m, r, c; std::cin >> n >> m >> r >> c; LL ans = 0; ans += 1ll * (m - c); ans += 1ll * (n - r) * (m - 1 + 1); ans += 1ll * (n - r) * 1 * (m - 1); std::cout << ans << "\n"; } return 0; }
B 结论
显然仅需考虑模 66 为 0。
一个显然的想法是先构造为全 3 的数,然后把某些位改成 6。
打了个表发现对于全 3 的数,模 66 的余数只有 3 和 33 两种情况,于是根据样例:
- 若余数为 33,考虑再加 33,即将后两位改成 6 即可;
- 若余数为 3,考虑再加 3033 即可。
若无法加则无解。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long //============================================================= //============================================================= //============================================================= int main() { //freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { int n; std::cin >> n; std::string ans; LL sum = 0; for (int i = 1; i <= n; ++ i) ans.push_back('3'), sum = (10 * sum + 3) % 66; if (sum == 33) { ans[n - 1] = '6', ans[n - 2] = '6'; } else { if (n == 1 || n == 3) ans = "-1"; else ans[n - 1] = '6', ans[n - 2] = '6', ans[n - 4] = '6'; } std::cout << ans << "\n"; } return 0; }
C 构造
妈的不会构造被鲨了。
首先通过样例猜测,当 为奇数时 ; 为偶数时 ,即两种情况都能取到上界。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const int kN = 2e5 + 10; //============================================================= int n, ans[kN]; LL k; //============================================================= void check() { int temp = 0; for (int i = 1; i <= n; ++ i) { if (i % 2 == 0) temp |= ans[i]; else temp &= ans[i]; } std::cout << "---" << temp << "\n"; } //============================================================= int main() { // freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; if (n & 1) { k = n; ans[n] = n; ans[n - 1] = n - 1; ans[n - 2] = 1; for (int i = 1; i <= n - 3; ++ i) ans[i] = i + 1; } else { k = (1ll << (((LL) log2(n)) + 1)) - 1l; std::map<int, bool> vis; std::vector<int> b[2]; int len = n; ans[n] = n; ans[n - 1] = k ^ n; if ((k ^ n) == 1) { len = 2; } else { len = 4; ans[n - 2] = ans[n - 1] - 1; ans[n - 3] = 1; } for (int i = n - len + 1; i <= n; ++ i) vis[ans[i]] = 1; for (int i = 1; i <= n; ++ i) if (!vis[i]) b[i % 2].push_back(i); for (int i = 1, j = 0; i <= n - len; ++ i, j ^= 1) ans[i] = b[j].back(), b[j].pop_back(); } // check(); std::cout << k << "\n"; for (int i = 1; i <= n; ++ i) std::cout << ans[i] << " "; std::cout << "\n"; } return 0; }
D 贪心,单调栈
先把每个数 2 的因子的次数 求出来,记 除掉所有 2 的因子后剩下的部分为 。
发现前缀 的最优操作方案,一定是将前缀 的操作方案中,某些位置的 2 的因子全部贡献给 得到的。显然只要 就应当产生贡献,又发现一个位置只能向其他位置贡献一次,于是考虑单调栈维护当前有哪些位置能向之后产生贡献,每次加入一个数 时不断弹栈将贡献给到 即可。
注意上述判断条件 中,当 获得了若干 2 的幂后会变得很大,因此需要单独写个比较函数,特判 较大时直接返回结果即可。
还需要写个快速幂,总时间复杂度 级别。
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const int kN = 2e5 + 10; const LL p = 1e9 + 7; //============================================================= int n; LL cnt2[kN], a[kN], b[kN], pw2[kN]; int top, st[kN]; //============================================================= LL qpow(LL x_, LL y_) { LL ret = 1; while (y_) { if (y_ & 1) ret = ret * x_ % p; x_ = x_ * x_ % p, y_ >>= 1ll; } return ret; } bool cmp(int p1_, int p2_) { if (pw2[p2_] > 30) return 1; return (1ll << pw2[p2_]) * b[p2_] >= b[p1_]; } //============================================================= int main() { // freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> n; for (int i = 1; i <= n; ++ i) cnt2[i] = 0; for (int i = 1; i <= n; ++ i) std::cin >> a[i], b[i] = a[i]; for (int i = 1; i <= n; ++ i) { while (b[i] % 2 == 0) ++ cnt2[i], b[i] /= 2; } top = 0; LL ans = 0; for (int i = 1; i <= n; ++ i) { ans += b[i]; pw2[i] = cnt2[i]; while (top && cmp(st[top], i)) { pw2[i] += pw2[st[top]]; ans -= b[st[top]] * (qpow(2, pw2[st[top]]) - 1 + p) % p; ans = (ans + p) % p; pw2[st[top]] = 0; -- top; } st[++ top] = i; ans += b[i] * (qpow(2, pw2[i]) - 1 + p) % p; ans %= p; std::cout << ans << " "; } std::cout << "\n"; } return 0; }
E 结论,数论分块
// /* By:Luckyblock */ #include <bits/stdc++.h> #define LL long long const LL kInf = 1e18 + 2077; //============================================================= LL x, y, z, k, ans; //============================================================= void check(LL r_, LL c1_, LL d1_) { LL c2 = kInf; for (LL r = r_ * k + k, l; r > r_ * k; r = l - 1) { l = std::max(r_ * k + 1, (LL) ceil(1.0 * (z - d1_) / ceil(1.0 * (z - d1_) / r))); c2 = std::min(c2, x * (l - r_ * k) + y * ((LL) ceil(1.0 * (z - d1_) / l))); } ans = std::min(ans, c1_ + c2); } //============================================================= int main() { // freopen("1.txt", "r", stdin); std::ios::sync_with_stdio(0), std::cin.tie(0); int T; std::cin >> T; while (T --) { std::cin >> x >> y >> z >> k; ans = kInf; for (LL round = 0; ; ++ round) { LL c1 = round * (k * x + y); LL d1 = round * (round + 1ll) / 2ll * k; if (d1 >= z) { ans = std::min(ans, c1); break; } check(round, c1, d1); } std::cout << ans << "\n"; } return 0; }
写在最后
怎么一堆思维结论题+打表,把我这种没脑子的呆瓜鲨了。
好想死掉。
作者@Luckyblock,转载请声明出处。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】