1. 程式人生 > 實用技巧 >[1/11]寒假訓練1-題解

[1/11]寒假訓練1-題解

A-CodeForces 1253A-Single Push

基礎模擬題,重定義a為陣列b-a的值,讓i指向首位,向後找到第一個非0數,讓j指向末尾,向前找到第一個非0數,若出現i>j則全為0,a和b已經相等輸出yes,反之繼續判斷區間[i,j]內的數是否全相等且大於0。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e3 + 10;
 
signed main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		int n;
		cin >> n;
		vector<int>a(n);
		for (int i = 0; i < n; i++) cin >> a[i];
		for (int i = 0, x; i < n; i++) cin >> x, a[i] = x - a[i];
		int i = 0, j = n - 1;
		while (i < n && !a[i]) i++;
		while (j >= i && !a[j]) j--;
		i++;
		while (i <= j && a[i] > 0 && a[i] == a[i - 1]) i++;
		cout << (i > j && a[j] >= 0 ? "YES" : "NO") << '\n';
	}
	return 0;
}

B-HDU - 2504-又見GCD

一般程式碼的時間複雜度是要在1e8以內的,所以這題c取值在1e6內可以想到直接暴力,gcd時間複雜度可視為O(logn),所以總時間複雜度為O(nlogn),而c要為b的倍數,可以將for迴圈優化成for(int i = 2 * b; i < 1e6; i += b)。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e3 + 10;

signed main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		int a, b;
		cin >> a >> b;
		for (int i = b + 1; i < 1e6; i++) {
			if (__gcd(a, i) == b) {
				cout << i << '\n';
				break;
			}
		}
	}
	return 0;
}

C-CodeForces - 1363A-Odd Selection

x個數的和為奇數那麼必須要保證x個數裡面有奇數個奇數,先統計下n個數裡面有多少個奇數c[1],偶數c[0],然後從貪心的角度入手,看x個裡面最多可以取到的奇數個奇數為v。如果v+c[0]能大於等於x,輸出yes,反之輸出no。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e3 + 10;

signed main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		int n, x;
		cin >> n >> x;
		int c[2] = {};
		for (int i = 0; i < n; i++) {
			int v;
			cin >> v;
			c[v % 2]++;
		}
		c[1] = min(c[1], x);
		if (c[1] && c[1] % 2 == 0) c[1]--;
		cout << (c[1] && c[0] + c[1] >= x ? "YES" : "NO") << '\n';
	}
	return 0;
}

D-AtCoder - abc125_d-Flipping Signs

不難發現,如果有偶數個負數,那麼可以通過操作全部變為正數,如果有奇數個負數,那麼最少也會剩下1個數為負數,所以統計負數的個數、絕對值最小的數以及所有數絕對值的和,便可直接計算答案。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 2e5 + 10;

signed main() {
	ios::sync_with_stdio(false);
	int n;
	cin >> n;
	vector<int>a(n);
	int s = 0, cnt = 0, f = 0, mn = 2e9;
	for (int i = 0; i < n; i++) {
		cin >> a[i];
		s += abs(a[i]);
		mn = min(mn, abs(a[i]));
		cnt += a[i] < 0;
		f |= a[i] == 0;
	}
	if (f || cnt % 2 == 0) cout << s << '\n';
	else cout << s - 2 * mn << '\n';
	return 0;
}

E-CodeForces - 1363B-Subsequence Hate

結果一定是類似於11100,00111,111,000這種,所以直接遍歷所有可能的分界線位置,然後取所有情況下左0右1和左1右0的最小答案。如下程式碼用字首和來取區間內0的個數和1的個數,由於s的長度最大為1e3,\(n^2\)也不會超出時間複雜度,所以也可以在for迴圈內套一層for迴圈來取0或1的個數。

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N = 5e3 + 10;

signed main() {
	ios::sync_with_stdio(false);
	int t;
	cin >> t;
	while (t--) {
		string s;
		cin >> s;
		int n = s.size();
		vector<vector<int>>c(2, vector<int>(n + 1));
		for (int i = 0; i < n; i++) {
			c[0][i + 1] = c[0][i] + (s[i] == '0');
			c[1][i + 1] = c[1][i] + (s[i] == '1');
		}
		int ans = 2e9;
		for (int i = 0; i <= n; i++) {
			ans = min(ans, n - (c[0][i] + (c[1][n] - c[1][i])));
			ans = min(ans, n - (c[1][i] + (c[0][n] - c[0][i])));
		}
		cout << ans << '\n';
	}
	return 0;
}