AtCoder Beginner Contest 238题解
本场打得比较摆烂,只到E题QAQ
A - Exponential or Quadratic
题目描述:给定正整数\(n\),判断式子\(2^n > n^2\)是否成立。
思路:显然只有当n = 2 , 3 , 4
时不成立
时间复杂度:\(O(1)\)
参考代码:
void solve() {
int n;
cin >> n;
if (n != 2 && n != 3 && n != 4) cout << "Yes\n";
else cout << "No\n";
return;
}
B - Pizza
题目描述:给定一块披萨,然后给你一个数组\(A\),每次你需要转动\(a_i\)角度之后,在12
点钟方向切一刀。问最终所有扇形中角度的最大值。
思路:显然让披萨转动和让刀转动等价,我们让刀转动,然后切的时候将对应角度标记为\(1\)。最后再使用双指针求最大值即可。
时间复杂度:\(O(n)\)
参考代码:
void solve() {
int n;
cin >> n;
vector<int>a(n + 1, 0);
for (int i = 1; i <= n; ++i) cin >> a[i];
vector<int>deg(361, 0);
deg[0] = 1; deg[360] = 1;
int cur = 0;
for (int i = 1; i <= n; ++i) {
cur = (cur + a[i]) % 360;
deg[cur] = 1;
}
int res = 0;
int p = 0, q = 1;
while (p < 360) {
while (deg[q] == 0) ++q;
res = max(res, q - p);
p = q;
q = p + 1;
}
cout << res << '\n';
return;
}
C - digitnum
题目描述:定义\(f(x)\)表示与\(x\)位数相同且小于等于\(x\)的数字的个数,对于给定的\(n\),求\(\sum\limits_{i = 1}^{n}f(i)\)。
思路:根据题意显然将\(n\)按照\(10\)的幂次分段,对于每一段,如果有\(m\)个数字,那么对答案的贡献就是\(\frac{m * (m + 1)}{2}\) 。比如\(10 \sim 99\)就是从\(1 \sim 90\)的累加。
时间复杂度:\(O(log_{10}n)\)
参考代码:
void solve() {
long long n;
cin >> n;
long long res = 0;
long long p = 10, q = 1;
const int mod = 998244353;
while (true) {
long long m = min(n , p - 1) - q + 1;
m %= mod;
res = (res + (m * (m + 1) / 2) % mod) % mod;
if (p > n) break;
p *= 10;
q *= 10;
}
cout << res << '\n';
return;
}
D - AND and SUM
题目描述:对于给定的\(a , s\),是否存在\(x , y\)使得以下条件成立:
x AND y = a
x + y = s
多组数据,对于每组数据若存在输出Yes
,否则输出No
。
思路:比较明显,我们可以先通过第一个约束条件将\(x , y\)的二进制表示中必须为\(1\)的找出来,求和为\(sum\)。若\(sum> s\)则显然没有;否则\(s = s - sum\)。然后对于每一个\(x , y\)没使用的二进制位,贪心的从\(s\)中减去,若最终\(s = 0\)则存在,否则不存在。
时间复杂度:\(O(60T)\)
参考代码:
void solve() {
long long a, s;
cin >> a >> s;
vector<int>cnt(60, 0);
long long sum = 0;
for (int i = 0; i < 60; ++i) {
cnt[i] += (a >> i) & 1;
if (cnt[i]) sum += 2ll << i;
}
if (sum > s) {
cout << "No" << '\n';
return;
}
s -= sum;
for (int i = 59; i >= 0; --i) {
if (cnt[i]) continue;
long long dx = 1ll << i;
if (dx <= s) s -= dx;
}
if (s == 0) cout << "Yes" << '\n';
else cout << "No" << '\n';
return;
}
E - Range Sums
题目描述:给你一个整数\(n\),表示有一个长度为\(n\)的正整数数组,告诉你\(q\)个条件,每个条件的形式为 lr rs
,表示\(\sum\limits_{i = lr}^{rs} a_i\) 。问是否可以通过这些条件知道\(\sum\limits_{i = 1}^{n}a_i\)。若能输出Yes
,否则输出No
。
思路:比较明显的图论题。对于每一个条件,可以根据前缀和的知识,抽象成从\(lr - 1\)到\(rs\)存在一条无向边。我们将条件读入并转化成图后,从\(0\)开始dfs
。若最终能访问到第\(n\)个点,则表示可以求出题目的和式,否则不能。
时间复杂度:\(O(n)\)
参考代码:
void solve() {
int n, q;
cin >> n >> q;
vector<vector<int>>graph(n + 1);
int u, v;
for (int i = 1; i <= q; ++i) {
cin >> u >> v;
graph[u - 1].push_back(v);
graph[v].push_back(u - 1);
}
vector<bool>vis(n + 1, false);
auto dfs = [&](auto dfs, int u)->void {
if (vis[u]) return;
vis[u] = true;
for (auto v : graph[u]) dfs(dfs, v);
return;
};
dfs(dfs, 0);
if (vis[n]) cout << "Yes" << '\n';
else cout << "No" << '\n';
return;
}
作者:cherish.
出处:https://home.cnblogs.com/u/cherish-/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。