AtCoder Beginner Contest 172
A - Calc (abc172 a)
题目大意
给定一个,输出
解题思路
模拟即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int a; cin >> a; cout << a + a * a + a * a * a << '\n'; return 0; }
B - Minor Change (abc172 b)
题目大意
给定两个字符串和 ,问同位置下不同字符的位置数。
解题思路
模拟即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); string s, t; cin >> s >> t; int ans = 0; for(int i = 0; i < s.size(); ++ i) ans += (s[i] != t[i]); cout << ans << '\n'; return 0; }
C - Tsundoku (abc172 c)
题目大意
给定两个数组和一个数,从 中取 个数,从 中取 个数,要求这 个数的和不超过,且 最大。
解题思路
给两个数组从小到大排个序,然后枚举,二分找到最大的,取最大的 即可。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; LL k; cin >> n >> m >> k; vector<LL> a(n), b(m); for(auto &i : a) cin >> i; for(auto &i : b) cin >> i; partial_sum(a.begin(), a.end(), a.begin()); partial_sum(b.begin(), b.end(), b.begin()); int ans = upper_bound(b.begin(), b.end(), k) - b.begin(); for(int i = 0; i < n; ++ i){ if (a[i] > k) break; ans = max(ans, i + 1 + int(upper_bound(b.begin(), b.end(), k - a[i]) - b.begin())); } cout << ans << '\n'; return 0; }
D - Sum of Divisors (abc172 d)
题目大意
定义为 的正因数的个数。
给定 ,求
解题思路
问题求一个数,所有因数的个数,乘以该数,求和。
转换下求和,考虑因数贡献,即对于一个因数,对于所有其倍数 ,都会对答案贡献 。
因此枚举因数,再枚举其倍数,求其倍数和即可。
时间复杂度为
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; LL ans = 0; for(int i = 1; i <= n; ++ i){ for(int j = i; j <= n; j += i) ans += j; } cout << ans << '\n'; return 0; }
E - NEQ (abc172 e)
题目大意
要求统计俩数组对的数量,满足长度均为, 数组中出现的数都在 之间,且俩俩互不相同,且对于下标 ,要求。
解题思路
对于数组,有 种取法,然后考虑数组 有多少种取法。
因为数组的所有取法都可以视为等价的,因此考虑数组 时,可以认为数组 为 。
此时相当于一个类错排问题,即从 中取 个数出来,要求第 个位置上不能是数字 。
对于原错排问题,即从 中取 个数出来,要求第 个位置上不能是数字 。其答案 。分别为
- 考虑原子问题中的排列,将第 个数, 放在第位,然后再选择前面的 中的一个位置交换,得到一个新排列。
- 考虑原子问题中的排列,第个数放在第位,第个数放在第位,然后交换这两个数,得到一个新排列。显然这第个数不一定是第 个数,它可以是前面任意一个。
在该问题多了个数,它不受任意条件限制。我们同样考虑递推求的值。
-
如果第 个位置放 ,那么和上面的计算方式一样。
-
如果第 个位置放不受限制的数,有 个数可以选,放了之后,第 个数也变成不受限制的数了,此时之后的状态,不受限制的数还是 个。
因此
答案就是
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; const int mo = 1e9 + 7; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; vector<int> dp(n + 1); dp[0] = 1; dp[1] = m - n; for(int i = 2; i <= n; ++ i){ dp[i] = (1ll * (m - n) * dp[i - 1] % mo + 1ll * (i - 1) * (dp[i - 1] + dp[i - 2]) % mo) % mo; } int ans = dp[n]; for(int i = m - n + 1; i <= m; ++ i){ ans = 1ll * ans * i % mo; } cout << ans << '\n'; return 0; }
F - Unfair Nim (abc172 f)
题目大意
给定堆石子,俩人玩 Nim
游戏,即每次可从一堆石子取走至少一个石子,不能操作者输。
现在可以从第堆拿一些石子放到第堆(可以不拿,但不能拿空), 问拿走石子数的最小值,使得后手必胜。或告知不可行。
解题思路
根据理论,全部石子数异或和为 则后手必胜。假设前两堆石子数和为, 后面的石子数异或和为 ,则题意转换为
求和,使得 ,且不能超过第一堆石子数。最大化。
神奇的是 ,即加法分为了不进位的加法和进位两部分。
这样原问题进一步变为,其中 。
注意如果是小于 或是 奇数则无解。
此时两个运算都是位运算,我们可以逐位考虑。对于和 的某一位的情况:
- 如果是 ,则 无解,无法做到。
- 如果是 ,则 在该位都必须为
- 如果是 ,则 仅有一个在该位为
- 如果是 ,则 在该位都必须为
因此我们可以构造出不大于第一堆石子数的最大的。
第一种情况相当于,此时无解。
由于的情况两者都必须为,因此我们可以初始化 的值为 ,然后从高位依次判断的每一位,看看让在该位为 会不会大于第一石子数,不大于则可以为。
神奇的代码
#include <bits/stdc++.h> using namespace std; using LL = long long; int main(void) { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n; cin >> n; vector<LL> a(n); for(auto &i : a){ cin >> i; } LL x = a[0] + a[1]; LL y = 0; for(int i = 2; i < n; ++ i) y = y ^ a[i]; auto solve = [&](){ if ((x - y < 0) || ((x - y) & 1)) return a[0] + 1; x = (x - y) / 2; if ((x & y) != 0) return a[0] + 1; if (x > a[0]) return a[0] + 1; LL ans = x; for(int i = 60; i >= 0; -- i){ if (((y >> i) & 1) && ans + (1ll << i) <= a[0]) ans += (1ll << i); } if (ans == 0) ans = a[0] + 1; return ans; }; LL ans = solve(); cout << a[0] - ans << '\n'; return 0; }
本文作者:~Lanly~
本文链接:https://www.cnblogs.com/Lanly/p/17066875.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步