1. 程式人生 > 其它 >Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128)A~C題解

Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128)A~C題解

A - Gold and Silver

對於每兩次交易來說,獲得的黃金數等於\(\frac {xa_{i}} {a_{i + 1}}\),也就是保證\(a_{i} > a_{i + 1}\)這兩次交易一定可以獲益。但是題目問的是獲得黃金數量的最大值,也就是說交易的次數一定為偶數次才能符合題意。那麼我們每次進行兩次交易,同時找到一個相鄰非遞增數對和相鄰非遞減數對標記,輸出即可

// Author: a1xt_CN
// Problem: A - Gold and Silver
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128)
// URL: https://atcoder.jp/contests/arc128/tasks/arc128_a
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Date: 2021-10-16 20:00:08

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int N = 200010;
int a[N];
bool vis[N];
int main() {
	int n;
	cin >> n;
	for (int i = 1;i <= n;++i) {
		cin >> a[i];
	}
	for (int i = 1;i <= n;++i) {
		while (i < n && a[i+1] >= a[i])
			++i;
		if (i < n)
			vis[i] = 1;
		else break;
		while (i < n && a[i] >= a[i+1])
			++i;
		vis[i] = 1;
	}
	for (int i = 1;i <= n;++i) {
		cout << vis[i] << ' ';
	}
	cout << endl;
	return 0;
}

B - Balls of Three Colors

這題很有意思。首先考慮一定可以的情況,那就是有兩種或者三種顏色的球數目相同。這樣我們可以將兩種個數相同的球變為第三種顏色的球,變換次數即相同顏色的球的對數。

除此之外就是兩兩不同的情況。我們可以發現,如果將兩種顏色球變為另外一種顏色的球,那麼被變顏色的球和變顏色的球個數差會變化3。如果我們要將兩兩不同的情況變為上一種一定可以的情況,當且僅當存在兩種顏色的球的個數之差是三的倍數。此條件不滿足,任意兩種顏色的球的個數都不會相等,因此一定無解;

為了表示方便,我們設各種球的個數分別為\(r,g,b,且3|(r - b)\),最後我們要將所有顏色的球變為\(G\)

。分兩種情況討論:

  • \(g ≥ (r - b) / 3\),這樣我們每次減少一個\(r\)和一個\(g\),總共減少\((r - b)/3\)\(r\)\(g\),使得\(r\)\(b\)全部變為\(b + 2(r - b)/3\),注意此時\(g≥0\)。所以接下來只要每次減少一個\(r\)和一個\(b\),總共減少\(b+2(r-b)/3\)次就可以將所有的球顏色變為\(G\)。答案為\(b + 3(r-b)/3 = r\)
  • \(g<(r-b)/3\),如果仍然按照上種方法做,會導致顏色為\(G\)的球不夠用。但此種情況並非無解。首先我們利用比較多的\(r\)\(b\)儘可能的轉為\(g\)
    ,轉\(b\)次。此時\(b=0,g = g+2b,r = r-b\),再將一個\(g\)和一個\(r\)轉為兩個\(b\),此時\(b = 2,g = g + 2b - 1,r = r- b - 1\),再將兩個\(b\)全部轉為\(g\),此時\(b = 0,g = g + 2b + 3,r = r - b - 3\),可以發現,經過這三次操作,\(g\)變多,\(r\)減少三個依然是三的倍數,因此重複上次操作即可將所有球轉為\(G\)。答案為\(b + (r - b) / 3 \times 3 = r\)
  • 綜上,答案為\(r\)

注意,因為要求最小值,所以要對所有可能取\(min\)

// Author: a1xt_CN
// Problem: B - Balls of Three Colors
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128)
// URL: https://atcoder.jp/contests/arc128/tasks/arc128_b
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Date: 2021-10-16 20:00:12

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int N = 200010;

int main() {
	int t;cin >> t;
	while (t--) {
		int r,g,b;
		cin >> r >> g >> b;
		if (r == g) {
			cout << r << endl;
			continue;
		}else if (g == b) {
			cout << g << endl;
			continue;
		}else if (r == b) {
			cout << r << endl;
			continue;
		}
		bool f = 0;
		int res = 1e9;
		if (abs(r - g) % 3 == 0) {
			res = min(res,max(r,g));
			f = 1;
		}
		if (abs(b - g) % 3 == 0) {
			res = min(res,max(b,g));
			f = 1;
		}
		if (abs(r - b) % 3 == 0) {
			res = min(res,max(r,b));
			f = 1;
		}
		if (!f)	puts("-1");
		else cout << res << endl;
	}
	return 0;
}

C - Max Dot

結論題。結論為,從末尾向前找的子序列中,將價值最大(價值指序列的和與序列長度的比值)的序列分配為當前可分配的最大值(即\(min(M,S/s)\),\(S\)為分配剩餘的總和,\(s\)為當前序列的長度,\(M\)為限制的最大值),其餘均為0;

證明:[參見官方題解](Editorial - Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128))

// Author: a1xt_CN
// Problem: C - Max Dot
// Contest: AtCoder - Daiwa Securities Co. Ltd. Programming Contest 2021(AtCoder Regular Contest 128)
// URL: https://atcoder.jp/contests/arc128/tasks/arc128_c
// Memory Limit: 1024 MB
// Time Limit: 2000 ms
// Date: 2021-10-16 20:00:16

#include <bits/stdc++.h>
using namespace std;

using ll = long long;
const int N = 5010;

int a[N];
int main() {
	int n,m,S;
	cin >> n >> m >> S;
	for (int i = 0;i < n;++i) {
		cin >> a[i];
	}
	double ans = 0;
	int p = n;
	while (p != 0 && S > 0) {
		int s = 0;ll sum = 0;
		int u = p - 1;
		double R = 0;
		for (int i = p - 1;i >= 0;--i) {
			s += 1,sum += a[i];
			if ((double)sum / s > R) {
				R = (double) sum / s;
				u = i;
			}
		}
		//cout <<"? "<< u << endl;
		s = sum = 0;
		for (int i = u;i < p;++i) {
			s += 1,sum += a[i];
		}
		double cnt = min((double) m,(double) S / s);
		ans += sum * cnt;
		S -= cnt * s;
		p = u;
	}
	printf("%.10lf\n",ans);
	return 0;
}