A.FashionabLee
题意:
正边形,通过任意旋转如果存在两条边,一条边平行于
轴,一条边平行于
轴,则输出
,否则输出
题解:
只需要是
的倍数即可
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; void solve() { int n; scanf("%d", &n); puts((n % 4) ? "NO" : "YES"); } int main() { int t; for (scanf("%d", &t); t >= 1; t--) solve(); }
B.
题意:
给定一个长度为的
串
,如果出现
这种形式,即
在前面
在后面,那么你可以选择消除
或者
中的任意一个。询问最短能消除成什么样子。
题解:
可以发现除了前导和后导
是不能删除的,中间的都可以删除,因此如果
为
,最终只剩下前导
和后导
,否则就是前导
+一个
+后导
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 1e5 + 5; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; char s[maxn]; void solve() { int n; scanf("%d %s", &n, s); int l, r; for (l = 0; l < n; l++) if (s[l] != '0') break; for (r = n - 1; r >= 0; r--) if (s[r] != '1') break; for (int i = 0; i < l; i++) putchar('0'); if (l < r) putchar('0'); for (int i = r + 1; i < n; i++) putchar('1'); puts(""); } int main() { int t; for (scanf("%d", &t); t >= 1; t--) solve(); }
C.RationalLee
题意:
把个数字
分给
个人,满足第
个人有
个数,使得每个人得到的最大值加最小值之和最大。如果某个人只有一个数字,他的贡献就为这个数值的两倍
题解:
将和
分别进行排序,把最大的几个数分配给
的人,然后每次取最大的一个数和最小的几个数分配给此时
最大的数即可
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef pair<int, int> pii; const int maxn = 2e5 + 5; const int INF = 0x3f3f3f3f; const int mod = 1e9 + 7; ll n, m, a[maxn], w[maxn], ans; void solve() { ans = 0; scanf("%lld%lld", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", &a[i]); for (int i = 1; i <= m; i++) scanf("%lld", &w[i]); sort(a + 1, a + n + 1); sort(w + 1, w + m + 1); int idx = 1; while (w[idx] == 1) { ans += a[n] * 2; n--; idx++; } int l = 1; while (idx <= m) { ans += a[n] + a[l]; l += w[m] - 1; n--; m--; } printf("%lld\n", ans); } int main() { int t; for (scanf("%d", &t); t >= 1; t--) solve(); }
D. TediousLee
题意:
一开始只有一个节点,每次操作可以让没有儿子节点的节点多一个儿子,让有一个儿子节点的节点多两个儿子,一个有三个儿子节点的节点不作变化。每次操作都对每个节点同时操作,询问经过次操作,可以找出多少个不相互交叉的爪子形状(一个父节点连着三个子节点)
题解:
找找规律可以发现level 的树是一个根节点,连着两个level
的树和一个level
的树组成的。因此
的答案必然包括
,这些都是两个level
的树和一个level
的树内的,不包括根节点。通过找规律发现,当
的时候根节点可以同三个子节点相连形成一个爪子。
#include <bits/stdc++.h> using namespace std; typedef long long ll; typedef unsigned long long ull; const int maxn = 2e6 + 5; const ll mod = 1e9 + 7; ll dp[maxn]; int main() { dp[1] = dp[2] = 0; for (int i = 3; i < maxn; i++) dp[i] = (dp[i - 1] + 2ll * dp[i - 2] + (i % 3 == 0) * 4ll) % mod; int t, x; for (scanf("%d", &t); t >= 1; t--) scanf("%d", &x), printf("%lld\n", dp[x]); return 0; }
E.DeadLee
题意:
有种食物和
个人,每种食物有
份,每个人喜欢
和
两种食物
。对于每个人如果
和
食物都有,则各吃一份;如果只有一种就只吃那一份;如果都没有就会把Lee吃了。询问Lee最终能否存活,能则输出
个人的出场顺序
题解:
反着找,先找那些每个要吃的人全都吃也不会不够的食物,让那些人只吃这个食物,那么另一样食物的需求就会减少一个,为了操作容易实现,并不是把这些人需求去掉,而是让另一种食物的数量加,结果是一样的,但是数量加
方便操作,同时把那个人加入数组,继续遍历下一个满足条件的食物,只到没有满足条件的食物或者已经满足所有人的要求则结束,以上操作用
即可。判断数组中是否有
个人,有则反向输出,否则Lee不能存活
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int maxn = 2e5 + 5; int n, m, w[maxn]; vector<pair<int, int>> G[maxn]; vector<int> ans; bool vis[maxn], v[maxn]; void dfs(int x) { v[x] = true; for (auto i : G[x]) { int x = i.first, y = i.second; w[x]++; if (!vis[y]) ans.push_back(y), vis[y] = true; if (!v[x] && G[x].size() <= w[x]) dfs(x); } } int main() { scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &w[i]); for (int i = 1; i <= m; i++) { int x, y; scanf("%d%d", &x, &y); G[x].push_back({y, i}), G[y].push_back({x, i}); } for (int i = 1; i <= n; i++) if (!v[i] && G[i].size() <= w[i]) dfs(i); if (ans.size() < m) puts("DEAD"); else { puts("ALIVE"); for (int i = m - 1; i >= 0; i--) printf("%d ", ans[i]); } return 0; }