目录
Superultra's Favorite Permutation
Kachina's Favorite Binary String
Twice
原题链接
思路分析
直接计数即可
时间复杂度:O(N)
AC代码
from bisect import *
import copy
import sys
from math import *
from math import inf
import heapq
from collections import Counter
from itertools import accumulate
from typing import *
import os
from types import GeneratorType
def bootstrap(f, stack=[]):
def wrappedfunc(*args, **kwargs):
if stack:
return f(*args, **kwargs)
else:
to = f(*args, **kwargs)
while True:
if type(to) is GeneratorType:
stack.append(to)
to = next(to)
else:
stack.pop()
if not stack:
break
to = stack[-1].send(to)
return to
return wrappedfunc
input = lambda: sys.stdin.readline().strip()
output = lambda x: sys.stdout.write(str(x) + '\n')
MII = lambda: map(int, input().split())
LMI = lambda: list(map(int, input().split()))
LI = lambda: list(input())
II = lambda: int(input())
I = lambda: input()
fmax = lambda x, y: x if x > y else y
fmin = lambda x, y: x if x < y else y
# sys.stdin = open('in.txt', 'r')
def solve():
n = II()
a = LMI()
res = 0
cnt = Counter(a)
for x in cnt.values():
res += x // 2
print(res)
pass
if __name__ == "__main__":
T = 1
T = II()
for _ in range(T):
solve()
Intercepted Inputs
原题链接
思路分析
找到两个数乘积为 k - 2 即可
时间复杂度:O(k)
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
void solve() {
int k;
std::cin >> k;
int n = -1, m = -1;
std::vector<int> a(k);
for (int i = 0; i < k; ++ i) {
std::cin >> a[i];
}
k -= 2;
std::set<int> st;
for (int x : a) {
if (k % x == 0 && st.contains(k / x)) {
n = x;
m = k / x;
break;
}
st.insert(x);
}
assert(n != -1 && m != -1);
std::cout << n << ' ' << m << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}
Superultra's Favorite Permutation
原题链接
Superultra's Favorite Permutation
思路分析
和上次div2C的构造思路类似
1~4 无法构造
从5开始,我们奇数放一边,偶数放一边,奇数相加和偶数相加都是合数,只需找到一对奇数偶数之和为合数,最小的pair 为 4 + 5 = 9
时间复杂度:O(N)
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
void solve() {
int n;
std::cin >> n;
if (n <= 4) {
std::cout << "-1\n";
return;
}
std::vector<int> p;
for (int i = 1; i <= n; i += 2) {
if (i == 5) {
continue;
}
p.push_back(i);
}
p.push_back(5);
p.push_back(4);
// 1 2 3 4 5
// 2 4 5 1 3
for (int i = 2; i <= n; i += 2) {
if (i == 4) {
continue;
}
p.push_back(i);
}
for (int i = 0; i < n; ++ i) {
std::cout << p[i] << " \n"[i + 1 == n];
}
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}
Sharky Surfing
原题链接
思路分析
直接堆模拟即可,就是在不得不拿的时候,拿前面能拿的当中最大的那个
时间复杂度:O(NlogN)
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
void solve() {
int n, m, L;
std::cin >> n >> m >> L;
std::vector<std::pair<int, int>> segs(n);
for (int i = 0; i < n; ++ i) {
int l, r;
std::cin >> l >> r;
segs[i] = {l, r};
}
std::vector<std::pair<int, i64>> p(m);
std::map<int, i64> f;
for (int i = 0; i < m; ++ i) {
int x, v;
std::cin >> x >> v;
p[i] = {x, v};
f[x] += v;
}
std::ranges::sort(p);
std::priority_queue<i64> pq;
int i = 0;
i64 cur = 1;
int ans = 0;
for (auto &[l, r] : segs){
while (i < p.size() && p[i].first < l) {
pq.push(p[i].second);
++ i;
}
while (cur < r - l + 2) {
if (pq.empty()) {
std::cout << "-1\n";
return;
}
cur += pq.top();
pq.pop();
++ ans;
}
}
std::cout << ans << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}
Kachina's Favorite Binary String
原题链接
Kachina's Favorite Binary String
思路分析
思维+构造
如果f(1, n) = 0,那么impossible
设第一个0的位置为st0,[[1, st0 - 1], n] 的值都等于 f(1, n)
我们可以找到st0
然后从st0 + 1 一直闻到 n - 1,记录上一次询问<st0, i - 1> 的值last
只要 f(st0, i) > last,那么s[i] = 1,否则为0
这样一共问了n次,但是没有问(st0, n),显然 (st0, n) = f(1, n),一开始就问过了
我们根据 last 和 f(1. n) 的关系即可求出 s[n]
刚好问了n次,比较极限(当然可以剪枝,但是最坏还是n次)
时间复杂度:O(N)
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
int query(int l, int r) {
std::cout << "? " << l << ' ' << r << std::endl;
int res;
std::cin >> res;
return res;
}
void solve() {
int n;
std::cin >> n;
int tot = query(1, n);
if (tot == 0) {
std::cout << "! IMPOSSIBLE" << std::endl;
return;
}
std::string s(n, '0');
int i = 2;
while (i < n && query(i, n) == tot) {
s[i - 2] = '1';
++ i;
}
s[i - 2] = '0';
int st0 = i - 1;
int last = 0;
for (; i < n; ++ i) {
int res = query(st0, i);
if (res > last) {
s[i - 1] = '1';
} else {
s[i - 1] = '0';
}
last = res;
}
if (last == tot) {
s[n - 1] = '0';
} else {
s[n - 1] = '1';
}
std::cout << "! " << s << std::endl;
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}
Ardent Flames
原题链接
思路分析
二分+差分
二分次数mid
对于 <x[i], h[i]>,要在mid次被击败,则
m - |p - x| >= ceil(h[i] / mid)
得出 x - (m - ceil(h[i] / mid)) <= p <= x + m - ceil(h[i] / mid)
我们差分对 每个怪物贡献的区间+1,然后对差分做前缀和,只要某个点被覆盖了k次以上,就返回true,否则false
时间复杂度:O(N log U logN),U为值域
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
void solve() {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> h(n), x(n);
for (int i = 0; i < n; ++ i) {
std::cin >> h[i];
}
for (int i = 0; i < n; ++ i) {
std::cin >> x[i];
}
auto check = [&](int mid) -> bool {
std::map<int, int> f;
for (int i = 0; i < n; ++ i) {
int val = m - (h[i] + mid - 1) / mid;
if (val < 0) {
continue;
}
++ f[x[i] - val];
-- f[x[i] + val + 1];
}
int s = 0;
for (auto &[pos, v] : f) {
s += v;
if (s >= k) {
return true;
}
}
return false;
};
int lo = 1, hi = std::ranges::max(h);
int ans = -1;
while (lo <= hi) {
int mid = (lo + hi) / 2;
if (check(mid)) {
ans = mid;
hi = mid - 1;
} else {
lo = mid + 1;
}
}
std::cout << ans << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}
Natlan Exploring
原题链接
思路分析
拓扑序dp+容斥
由于我不会莫比乌斯,所以用了暴力容斥
预处理 minp[x],即 x 的最小质因子
然后预处理 facs[i],即 a[i] 的质因子集合
定义 f[i] 为 到达 i 的路径数,sum[p1 p2 ... pk] 为 到达 被 p1 p2 ... pk整除的节点的路径数
那么对于第i个节点 而言,它有 len(facs[i])个不同的质因子
直接累加 Σ sum[p1 p2 ... pk] 显然是会重复的,我们需要做容斥(容斥原理自行搜索)
即:f[i] += Σ sum[p1 p2 ... pk] * sign,sgn = (-1)^{k + 1}
然后对于 sum[p1 p2 ... pk] 累加 f[i] 即可
时间复杂度:O(NlnM + 2^ln(M) * n * ln(M))
AC代码
#include <bits/stdc++.h>
// #define DEBUG
using u32 = unsigned;
using i64 = long long;
using u64 = unsigned long long;
constexpr int inf32 = 1E9 + 7;
constexpr i64 inf64 = 1E18 + 7;
template<class T>
constexpr T power(T a, i64 b) {
T res = 1;
for (; b; b /= 2, a *= a) {
if (b % 2) {
res *= a;
}
}
return res;
}
constexpr i64 mul(i64 a, i64 b, i64 p) {
i64 res = a * b - i64(1.L * a * b / p) * p;
res %= p;
if (res < 0) {
res += p;
}
return res;
}
template<i64 P>
struct MLong {
i64 x;
constexpr MLong() : x{} {}
constexpr MLong(i64 x) : x{norm(x % getMod())} {}
static i64 Mod;
constexpr static i64 getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(i64 Mod_) {
Mod = Mod_;
}
constexpr i64 norm(i64 x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr i64 val() const {
return x;
}
explicit constexpr operator i64() const {
return x;
}
constexpr MLong operator-() const {
MLong res;
res.x = norm(getMod() - x);
return res;
}
constexpr MLong inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
constexpr MLong &operator*=(MLong rhs) & {
x = mul(x, rhs.x, getMod());
return *this;
}
constexpr MLong &operator+=(MLong rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MLong &operator-=(MLong rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MLong &operator/=(MLong rhs) & {
return *this *= rhs.inv();
}
friend constexpr MLong operator*(MLong lhs, MLong rhs) {
MLong res = lhs;
res *= rhs;
return res;
}
friend constexpr MLong operator+(MLong lhs, MLong rhs) {
MLong res = lhs;
res += rhs;
return res;
}
friend constexpr MLong operator-(MLong lhs, MLong rhs) {
MLong res = lhs;
res -= rhs;
return res;
}
friend constexpr MLong operator/(MLong lhs, MLong rhs) {
MLong res = lhs;
res /= rhs;
return res;
}
friend constexpr std::istream &operator>>(std::istream &is, MLong &a) {
i64 v;
is >> v;
a = MLong(v);
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const MLong &a) {
return os << a.val();
}
friend constexpr bool operator==(MLong lhs, MLong rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MLong lhs, MLong rhs) {
return lhs.val() != rhs.val();
}
};
template<>
i64 MLong<0LL>::Mod = i64(1E18) + 9;
template<int P>
struct MInt {
int x;
constexpr MInt() : x{} {}
constexpr MInt(i64 x) : x{norm(x % getMod())} {}
static int Mod;
constexpr static int getMod() {
if (P > 0) {
return P;
} else {
return Mod;
}
}
constexpr static void setMod(int Mod_) {
Mod = Mod_;
}
constexpr int norm(int x) const {
if (x < 0) {
x += getMod();
}
if (x >= getMod()) {
x -= getMod();
}
return x;
}
constexpr int val() const {
return x;
}
explicit constexpr operator int() const {
return x;
}
constexpr MInt operator-() const {
MInt res;
res.x = norm(getMod() - x);
return res;
}
constexpr MInt inv() const {
assert(x != 0);
return power(*this, getMod() - 2);
}
constexpr MInt &operator*=(MInt rhs) & {
x = 1LL * x * rhs.x % getMod();
return *this;
}
constexpr MInt &operator+=(MInt rhs) & {
x = norm(x + rhs.x);
return *this;
}
constexpr MInt &operator-=(MInt rhs) & {
x = norm(x - rhs.x);
return *this;
}
constexpr MInt &operator/=(MInt rhs) & {
return *this *= rhs.inv();
}
friend constexpr MInt operator*(MInt lhs, MInt rhs) {
MInt res = lhs;
res *= rhs;
return res;
}
friend constexpr MInt operator+(MInt lhs, MInt rhs) {
MInt res = lhs;
res += rhs;
return res;
}
friend constexpr MInt operator-(MInt lhs, MInt rhs) {
MInt res = lhs;
res -= rhs;
return res;
}
friend constexpr MInt operator/(MInt lhs, MInt rhs) {
MInt res = lhs;
res /= rhs;
return res;
}
friend constexpr std::istream &operator>>(std::istream &is, MInt &a) {
i64 v;
is >> v;
a = MInt(v);
return is;
}
friend constexpr std::ostream &operator<<(std::ostream &os, const MInt &a) {
return os << a.val();
}
friend constexpr bool operator==(MInt lhs, MInt rhs) {
return lhs.val() == rhs.val();
}
friend constexpr bool operator!=(MInt lhs, MInt rhs) {
return lhs.val() != rhs.val();
}
};
template<>
int MInt<0>::Mod = 998244353;
template<int V, int P>
constexpr MInt<P> CInv = MInt<P>(V).inv();
constexpr int P = 998244353;
using Z = MInt<P>;
std::vector<int> minp, primes;
void sieve(int n) {
minp.assign(n + 1, -1);
primes.clear();
for (int i = 2; i <= n; ++ i) {
if (minp[i] == -1){
minp[i] = i;
primes.push_back(i);
}
for (int j : primes) {
if (i * j > n) break;
minp[i * j] = j;
if (j == minp[i]) break;
}
}
}
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
const int M = std::ranges::max(a);
sieve(M);
std::vector<std::vector<int>> facs(n);
for (int i = 0; i < n; ++ i) {
int x = a[i];
while (x > 1) {
facs[i].push_back(minp[x]);
int p = minp[x];
while (x % p == 0) {
x /= p;
}
}
}
std::vector<Z> f(n), sum(M + 1);
f[0] = 1;
for (int i = 0; i < n; ++ i) {
std::vector<int> nodes;
for (int j = 1, ed = 1 << facs[i].size(); j < ed; ++ j) {
int sgn = -1, p = 1;
Z s = 0;
for (int k = 0; k < facs[i].size(); ++ k) {
if (j >> k & 1) {
sgn *= -1;
p *= facs[i][k];
}
}
f[i] += sum[p] * sgn;
nodes.push_back(p);
}
for (int v : nodes) {
sum[v] += f[i];
}
}
std::cout << f[n - 1] << '\n';
}
int main() {
std::ios::sync_with_stdio(false);
std::cin.tie(nullptr);
#ifdef DEBUG
int START = clock();
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int t = 1;
// std::cin >> t;
while (t --) {
solve();
}
#ifdef DEBUG
std::cerr << "run-time: " << clock() - START << '\n';
#endif
return 0;
}