ACM-ICPC 2018 焦作赛区网络预赛
A. Magic Mirror
签到
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
std::string s;
std::cin >> s;
for (auto & c : s) {
if (c >= 'a' && c <= 'z') {
c -= 32;
}
}
std::cout << (s == "JESSIE" ? "Good guy!" : "Dare you say that again?") << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
B. Mathematical Curse
题意:一开始值为\(k\),需要从\(n\)个数里选\(m\)个来进行\(m\)个运算。求可以得到的最大值。
\(f[i][j], g[i][j]\)分别表示前\(i\)个里选了\(j\)个的最大最小值。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int n, m, k;
std::cin >> n >> m >> k;
std::vector<int> a(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i];
}
std::string s;
std::cin >> s;
auto get = [&](i64 a, char op, i64 b) -> i64 {
if (op == '+') {
return a + b;
} else if (op == '-') {
return a - b;
} else if (op == '*') {
return a * b;
} else {
return a / b;
}
};
const i64 inf = 1e9;
std::vector<i64> f(m + 1, -inf), g(m + 1, inf);
f[0] = g[0] = k;
for (int i = 0; i < n; ++ i) {
for (int j = std::min(m, i + 1); j >= 1; -- j) {
i64 x = get(f[j - 1], s[j - 1], a[i]), y = get(g[j - 1], s[j - 1], a[i]);
f[j] = std::max({f[j], x, y});
g[j] = std::min({g[j], x, y});
}
}
std::cout << f[m] << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
F. Modular Production Line
题意:每段区间贡献一个值。一个区间最多选一次,没个点最多被覆盖\(k\)次。求最大价值。
把每个区间看作一个整体\(l\)向\(r+1\)连\(-w\)的边。相邻点连容量为无穷花费为\(0\)的边。然后源点向最左侧点、最右侧点向汇点连\(k\)容量的边。跑最小费用流。
需要离散化一下。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
const int N = 1010, M = (1000 + 1000) * 2 + 10, INF = 0x3f3f3f3f;
int head[N], ver[M], cap[M], cost[M], next[M], tot;
int dist[N], h[N], pre[N];
int n, m, k, S, T;
void add(int x, int y, int c, int d) {
ver[tot] = y; cap[tot] = c; cost[tot] = d; next[tot] = head[x]; head[x] = tot ++ ;
ver[tot] = x; cap[tot] = 0; cost[tot] = -d; next[tot] = head[y]; head[y] = tot ++ ;
}
bool dijkstra() {
using PII = std::pair<int, int>;
memset(dist, 0x3f, sizeof dist);
std::priority_queue<PII, std::vector<PII>, std::greater<PII> > heap;
dist[S] = 0;
heap.push({dist[S], S});
while (heap.size()) {
auto [d, u] = heap.top(); heap.pop();
if (d != dist[u]) {
continue;
}
for (int i = head[u]; ~i ; i = next[i]) {
int v = ver[i];
if (cap[i] && dist[v] > d + h[u] - h[v] + cost[i]) {
dist[v] = d + h[u] - h[v] + cost[i];
pre[v] = i;
heap.push({dist[v], v});
}
}
}
return dist[T] != 0x3f3f3f3f;
}
void solve() {
std::cin >> n >> k >> m;
memset(head, -1, sizeof head);
tot = 0;
memset(h, 0, sizeof h);
std::vector<std::tuple<int, int, int>> a(m);
std::vector<int> b;
for (int i = 0; i < m; ++ i) {
int u, v, w;
std::cin >> u >> v >> w;
a[i] = {u, v, w};
b.push_back(u);
b.push_back(u + 1);
b.push_back(v);
b.push_back(v + 1);
}
b.push_back(n + 1);
std::sort(b.begin(), b.end());
b.erase(std::unique(b.begin(), b.end()), b.end());
auto get = [&](int x) -> int {
return std::lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
};
int N = b.size();
S = 0, T = N + 2;
for (auto & [u, v, w] : a) {
add(get(u), get(v + 1), 1, -w);
}
add(S, 1, k, 0);
for (int i = 0; i <= N; ++ i) {
add(i, i + 1, INF, 0);
}
add(N + 1, T, k, 0);
int flow = 0, cost = 0;
while (dijkstra()) {
for (int i = 0; i <= N + 2; ++ i) {
h[i] += dist[i];
}
int minf = INF;
for (int i = T; i != S; i = ver[pre[i] ^ 1]) {
minf = std::min(minf, cap[pre[i]]);
}
for (int i = T; i != S; i = ver[pre[i] ^ 1]) {
cap[pre[i]] -= minf;
cap[pre[i] ^ 1] += minf;
}
flow += minf;
cost += minf * h[T];
}
std::cout << -cost << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
G. Give Candiies
\(2^{n-1} mod (1e9 + 7)\)。根据欧拉定理降幂。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
const int mod = 1e9 + 7;
int power(int a, int b) {
int res = 1;
for (;b;b >>= 1, a = (i64)a * a % mod) {
if (b & 1) {
res = (i64)res * a % mod;
}
}
return res;
}
void solve() {
std::string s;
std::cin >> s;
int n = 0;
for (auto & c : s) {
n = (n * 10ll % (mod - 1) + c - '0') % (mod - 1);
}
std::cout << power(2, n - 1 + mod - 1) << "\n";
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
I. Save the Room
题意:求\(1\times 1 \times 2\)的物品能不能放满\(a\times b\times c\)的立方体。
有一个是偶数就能放满。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
void solve() {
int a, b, c;
while (std::cin >> a >> b >> c) {
if (a == 0) {
break;
}
if (a * b * c % 2 == 0) {
std::cout << "Yes\n";
} else {
std::cout << "No\n";
}
}
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
J. Patricipate in E-sports
高精度,用的java
点击查看代码
import java.util.*;
import java.math.BigInteger;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int t = scanner.nextInt();
while (t-- > 0) {
BigInteger n = new BigInteger(scanner.next());
solve(n);
}
scanner.close();
}
public static void solve(BigInteger n) {
boolean f1 = check(n);
BigInteger product = n.multiply(n.subtract(BigInteger.ONE)).divide(BigInteger.TWO);
boolean f2 = check(product);
if (f1 && f2) {
System.out.println("Arena of Valor");
} else if (f1) {
System.out.println("Hearth Stone");
} else if (f2) {
System.out.println("Clash Royale");
} else {
System.out.println("League of Legends");
}
}
private static boolean check(BigInteger n) {
BigInteger l = BigInteger.ZERO;
String s = "1";
for (int i = 0; i < 200; ++ i) {
s = s.concat("0");
}
BigInteger r = new BigInteger(s);
while (l.compareTo(r) < 0) {
BigInteger mid = l.add(r).divide(BigInteger.TWO);
BigInteger midSq = mid.multiply(mid);
if (midSq.compareTo(n) >= 0) {
r = mid;
} else {
l = mid.add(BigInteger.ONE);
}
}
return l.multiply(l).equals(n);
}
}
K. Transport Ship
题意:体积为\(v_i\)的物品有\(2^{c_i} - 1\)个。求装满\(s\)的方案数。
将\(i\)二进制拆分,就变成了\(01\)背包求方案数。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
const int mod = 1e9 + 7;
void solve() {
int n, q;
std::cin >> n >> q;
std::vector<int> a(n), b(n);
for (int i = 0; i < n; ++ i) {
std::cin >> a[i] >> b[i];
}
const int S = 10000;
std::vector<int> f(S + 1);
f[0] = 1;
for (int i = 0; i < n; ++ i) {
for (int j = 0; j < b[i]; ++ j) {
int w = a[i] * (1 << j);
for (int k = S; k >= w; -- k) {
f[k] = (f[k] + f[k - w]) % mod;
}
}
}
while (q -- ) {
int s;
std::cin >> s;
std::cout << f[s] << "\n";
}
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}
L. Poor God Water
题意:可以转化为:一个只包含\(1, 2, 3\)的序列,相邻的三个不能有和给定非法的三元组相同的,求这样的序列有多少个。
记\(f[i][a][b][c]\)为第\(i, i - 1, i - 2\)个分别是\(a, b, c\)的方案数,那么可以从\(f[i - 1][b][c][d]\)转移过来。方向合法状态只有\(20\)个,可以用矩阵快速幂优化。
点击查看代码
#include <bits/stdc++.h>
using i64 = long long;
const int mod = 1e9 + 7;
const int N = 20;
using Mat = std::array<std::array<int, N>, N>;
void clear(Mat & m) {
for (int i = 0; i < N; ++ i) {
for (int j = 0; j < N; ++ j) {
m[i][j] = 0;
}
}
}
void set_one(Mat & m) {
clear(m);
for (int i = 0; i < N; ++ i) {
m[i][i] = 1;
}
}
Mat operator * (const Mat & a, const Mat & b) {
Mat res;
clear(res);
for (int k = 0; k < N; ++ k) {
for (int i = 0; i < N; ++ i) {
if (a[i][k] == 0) {
continue;
}
for (int j = 0; j < N; ++ j) {
res[i][j] = (res[i][j] + (i64)a[i][k] * b[k][j] % mod) % mod;
}
}
}
return res;
}
Mat A, B;
void init() {
std::set<int> s;
for (int i = 1; i <= 3; ++ i) {
for (int j = 1; j <= 3; ++ j) {
for (int k = 1; k <= 3; ++ k) {
s.insert(i * 100 + j * 10 + k);
}
}
}
s.erase(111);
s.erase(222);
s.erase(333);
s.erase(132);
s.erase(231);
s.erase(313);
s.erase(323);
clear(A);
clear(B);
std::vector<int> a;
for (auto & x : s) {
a.push_back(x);
}
std::map<int, int> id;
int idx = 0;
for (int i = 0; i < N; ++ i) {
id[a[i]] = idx ++ ;
A[i][0] = 1;
}
for (int i = 0; i < N; ++ i) {
for (int j = 0; j < N; ++ j) {
if (a[i] / 10 == a[j] % 100) {
B[i][j] = 1;
}
}
}
}
Mat power(Mat a, i64 b) {
Mat res;
set_one(res);
for (;b;b >>= 1, a = a * a) {
if (b & 1) {
res = res * a;
}
}
return res;
}
void solve() {
i64 n;
std::cin >> n;
if (n == 1) {
std::cout << 3 << "\n";
} else if (n == 2) {
std::cout << 3 * 3 << "\n";
} else {
n -= 3;
auto res = power(B, n) * A;
int ans = 0;
for (int i = 0; i < N; ++ i) {
ans = (ans + res[i][0]) % mod;
}
std::cout << ans << "\n";
}
}
int main() {
std::ios::sync_with_stdio(false), std::cin.tie(0), std::cout.tie(0);
int t = 1;
init();
std::cin >> t;
while (t -- ) {
solve();
}
return 0;
}

浙公网安备 33010602011771号