B
考虑子集枚举,。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
vector<i64> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
int ans = 0;
function<void(int, i64)> dfs = [&](int i, i64 sum) {
if (i == n) {
if (sum != -1 && __builtin_popcount(sum) == k) {
ans++;
}
return;
}
dfs(i + 1, sum & a[i]);
dfs(i + 1, sum);
};
dfs(0, -1);
cout << ans << '\n';
return 0;
}
C
本题弱化版:https://atcoder.jp/contests/arc153/tasks/arc153_b。
D
实际上是 ,直接算,。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, p;
cin >> n >> p;
i64 ans = 2;
for (int i = 0; i < n; i++) {
ans = ans * ans % p;
}
cout << ans << '\n';
return 0;
}
E
均分,大的放后面, 。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
i64 s;
cin >> n >> s;
vector<i64> a(n);
for (int i = 0; i < n; i++) {
a[i] = s / n;
if (i >= n - s % n) {
a[i]++;
}
}
for (int i = 0; i < n; i++) {
cout << a[i] << " \n"[i == n - 1];
}
return 0;
}
F
考虑离线并查集,算出每两滴墨隔多久就会连接到一起,。
双倍经验:https://codeforces.com/contest/1851/problem/G。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
using Point = complex<double>;
struct UnionFind {
int n;
vector<int> f;
UnionFind(const int &n = 0) : n(n), f(n) {
iota(f.begin(), f.end(), 0);
}
int get(int x) {
while (x != f[x]) {
x = f[x] = f[f[x]];
}
return x;
}
bool unite(int x, int y) {
x = get(x), y = get(y);
if (x != y) {
f[y] = x;
return 1;
}
return 0;
}
bool united(int x, int y) {
return get(x) == get(y);
}
};
constexpr int inf = 1E9;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<Point> p(n);
vector<int> v(n);
for (int i = 0; i < n; i++) {
int x, y;
cin >> x >> y;
p[i] = Point(x, y);
cin >> v[i];
}
vector<array<int, 3>> e;
for (int i = 0; i < n; i++) {
for (int j = i + 1; j < n; j++) {
if (v[i] + v[j] == 0) {
e.push_back({inf, i, j});
} else {
e.push_back({int(ceil(abs(p[i] - p[j]) / (v[i] + v[j]))), i, j});
}
}
}
sort(e.begin(), e.end());
int m;
cin >> m;
vector<array<int, 2>> qry(m);
for (int i = 0; i < m; i++) {
int t;
cin >> t;
qry[i] = {t, i};
}
sort(qry.begin(), qry.end());
vector<int> ans(m);
UnionFind f(n);
int cnt = n;
int N = e.size();
int j = 0;
for (auto &[t, i] : qry) {
while (j < N && e[j][0] <= t) {
if (f.unite(e[j][1], e[j][2])) {
cnt--;
}
j++;
}
ans[i] = cnt;
}
for (int i = 0; i < m; i++) {
cout << ans[i] << '\n';
}
return 0;
}
G
注意到题目中说保证 中元素至少有 个数字互不相同。
那么若 中有 个不同数字,答案为 。
若有 个不同数字,说明有两个数字出现两次,就 减去重复的。
不考虑预处理,。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
constexpr int P = 1000000007;
vector<i64> fac, ifac;
i64 power(i64 a, i64 b, int p = P) {
i64 res = 1;
for (; b; b >>= 1, a = a * a % p) {
if (b & 1) {
res = res * a % p;
}
}
return res;
}
i64 inv(i64 x) {
return power(x, P - 2);
}
void init(int N) {
fac.assign(N + 1, 0);
ifac.assign(N + 1, 0);
fac[0] = 1;
for (int i = 1; i <= N; i++) {
fac[i] = fac[i - 1] * i % P;
}
ifac[N] = inv(fac[N]);
for (int i = N - 1; i >= 0; i--) {
ifac[i] = ifac[i + 1] * (i + 1) % P;
}
}
i64 C(int n, int m) {
if (m < 0 || m > n) {
return 0;
}
return fac[n] * ifac[m] % P * ifac[n - m] % P;
}
void solve() {
int n, k;
cin >> n >> k;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
unordered_map<int, int> s;
for (int i = 0; i < n; i++) {
s[a[i]]++;
}
if (s.size() == n) {
cout << C(n, k) << '\n';
} else {
int l = -1, r = -1;
for (int i = 0; i < n; i++) {
if (s[a[i]] == 2) {
if (l == -1) {
l = i;
} else if (r == -1) {
r = i;
}
}
}
cout << (C(n, k) - C(n - (r - l + 1), k - 1) + P) % P << '\n';
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
init(1E5);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
H
取 ,每次两个人战斗,显然大于等于某个值的人都有可能获胜,只要让他参与最后一次战斗,二分找到这个值。
。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<int> a(n);
for (int i = 0; i < n; i++) {
cin >> a[i];
}
vector<array<int, 2>> b(n);
for (int i = 0; i < n; i++) {
b[i] = {a[i], i};
}
sort(b.begin(), b.end());
int ans = 0;
int l = 0, r = n - 1;
while (l <= r) {
int m = (l + r) >> 1;
int sum = b[n - 1][0];
for (int i = n - 2; i >= 0; i--) {
if (i != m) {
sum = (sum + b[i][0]) / 2;
}
}
if (sum <= b[m][0]) {
r = m - 1;
ans = m;
} else {
l = m + 1;
}
}
string s(n, '0');
for (int i = ans; i < n; i++) {
s[b[i][1]] = '1';
}
cout << s << '\n';
return 0;
}
I
根据右端点排序后贪心,。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin >> n;
vector<pair<int, int>> a(n);
for (int i = 0; i < n; i++) {
auto &[r, l] = a[i];
cin >> l >> r;
}
sort(a.begin(), a.end());
int ans = 0;
int pre = -1;
int cur = -1;
for (int i = 0; i < n; i++) {
auto &[r, l] = a[i];
if (l <= cur) {
continue;
}
if (l <= pre) {
ans++;
cur = r;
} else {
pre = r;
}
}
cout << ans << '\n';
return 0;
}
J
本来我感觉都是 NO,但是样例说 的时候是 YES,那又感觉似乎只有 是 YES。
K
感觉不需要操作 ,发现只要 交替即可,答案为 。
L
数位 。
M
存在 和 边,那么 是 的孙子,那么枚举 ,。
C++ Code
#include "bits/stdc++.h"
using namespace std;
using i64 = long long;
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n, m;
cin >> n >> m;
vector<int> deg(n);
vector<vector<int>> g(n);
for (int i = 0; i < m; i++) {
int u, v;
cin >> u >> v;
u--, v--;
deg[u]++;
g[v].push_back(u);
}
vector<i64> ans(n);
for (int y = 0; y < n; y++) {
for (auto &z : g[y]) {
ans[z] += deg[y];
}
}
for (int i = 0; i < n; i++) {
cout << ans[i] << " \n"[i == n - 1];
}
return 0;
}