VP Educational Codeforces Round 47 (Rated for Div. 2)


A. Game Shopping

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> a(n), b(m);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    for (int i = 0; i < m; ++ i) {
    	std::cin >> b[i];
    }

    int ans = 0;
    for (int i = 0, j = 0; i < n && j < m; ++ i) {
    	if (b[j] >= a[i]) {
    		++ ans;
    		++ j;
    	}
    }


    std::cout << ans << "\n";
}


B. Minimum Ternary String

题意:给你一个只包含\(0, 1, 2\)的数组,你可以交换相邻的\(1,0\)或者\(1, 2\),求可以得到的最小字典序。

我们可以把所有1都移动到一个2的前面,为了字典序最小,应该把这些1都移动第一个2前面。

点击查看代码
void solve() {
    std::string s;
    std::cin >> s;
    int n = s.size();
    std::string a, b;
    for (int i = 0; i < n; ++ i) {
    	if (s[i] != '1') {
    		a += s[i];
    	} else {
    		b += s[i];
    	}
    }

    if (b.empty() || a.empty()) {
    	std::cout << s << "\n";
    } else {
    	for (int i = 0; i < a.size(); ++ i) {
    		if (a[i] == '2') {
    			a = a.substr(0, i) + b + a.substr(i);
    			std::cout << a << "\n";
    			return;
    		}
    	}

    	std::cout << a + b << "\n";
    }
}

C. Annoying Present

题意:给你\(m\)\(x_i, d_i\),每次你选择一个位置\(p\),使得\(sum += \sum_{j=1}^{n} x_i + d_i \times |p - j|\)。求\(sum\)最大。

显然\(x_i\)与操作位置无关,直接加上\(n\)个。对于\(d_i\),如果它大于等于\(0\),我们希望它乘的数的和最大,如果小于\(0\),希望它乘的数的和最小,那么我们可以预处理找出可以得到的\(\sum_{j=1}^{n} |p - j|\)最大的位置和最小的位置。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<i64> x(m), d(m);
    i64 sum = 0;
    for (int i = 1; i <= n; ++ i) {
    	sum += i - 1;
    }

    i64 max = sum, min = sum;
    for (int i = 2; i <= n; ++ i) {
    	sum += i - 1 - (n - i + 1);
    	max = std::max(max, sum);
    	min = std::min(min, sum);
    }

    i64 ans = 0;
    for (int i = 0; i < m; ++ i) {
    	std::cin >> x[i] >> d[i];
    	ans += x[i] * n;
    	if (d[i] >= 0) {
    		ans += d[i] * max;
    	} else {
    		ans += d[i] * min;
    	}
    }

    std::cout << std::fixed << std::setprecision(12);
    std::cout << (double)ans / n << "\n";
}

D. Relatively Prime Graph

题意:给你\(n\)个点,你要构造\(m\)条边,使得每条边\((u, v)\)都有\(gcd(u, v) = 1\),且图联通。

首先想要图联通,\(m\)至少是\(n-1\)
然后我们可以发现,\(1\)可以产生\(n-1\)条边,\(2\)可以产生\(n - \lfloor \frac{n}{2} \rfloor\)条边,于是我们可以猜测如果暴力找的话很快就能找到。

点击查看代码
void solve() {
	int n, m;
	std::cin >> n >> m;

	if (m < n - 1) {
		std::cout << "Impossible\n";
		return;
	}

	std::vector<std::pair<int, int>> ans;
	for (int i = 1; i <= n && ans.size() < m; ++ i) {
		for (int j = i + 1; j <= n && ans.size() < m; ++ j) {
			if (std::gcd(i, j) == 1) {
				ans.emplace_back(i, j);
			}
		}
	}

	if (ans.size() < m) {
		std::cout << "Impossible\n";
	} else {
		std::cout << "Possible\n";
		for (auto & [u, v] : ans) {
			std::cout << u << " " << v << "\n";
		}
	}
}

E. Intercity Travelling

题意:你要从\(1\)\(n\),每次移动花费\(a_s\)的代价,其中\(s\)是连续的不休息次数加一,每个点有\(\frac{1}{2}\)的概率让你休息,你在\(1\)号点已经休息过了。需要求出到达\(n\)的代价的期望乘上\(2^{n-1}\)

由于\(1\)是固定休息的,那么其它点关于休不休息有\(2^{n-1}\)可能,也就是期望的分母是\(2^{n-1}\),那么答案要求乘上这个相当于把它消去了。
那么我们可以每个\(a_i\)会贡献多少次,这个需要讨论一下,因为如果\(a_i\)\(pos\)得到,那么\([pos - i, pos - 1]\)都不能休息,其它\(n - i - 1\)个位置随便选,但\(1\)号点固定的,如果\(pos = i\),那么有\(n - i\)个位置随便选。那么就是两种情况加起来。
答案为\(\sum_{i=1}^{n} (2^{n-i} + (n - i) \times 2^{n-i-1}) \times a_i\)

代码省略取模类

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n + 1);
    for (int i = 1; i <= n; ++ i) {
    	std::cin >> a[i];
    }

    Z ans = 0;
    for (int i = 1; i <= n; ++ i) {
    	ans += (power<Z>(2, n - i) + (n - i) * power<Z>(2, n - i - 1)) * a[i];
    }

    std::cout << ans << "\n";
}
posted @ 2025-03-30 17:37  maburb  阅读(14)  评论(0)    收藏  举报