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;
}
posted @ 2025-05-26 17:37  maburb  阅读(31)  评论(0)    收藏  举报