[1/11]寒假訓練1-題解
阿新 • • 發佈:2021-01-11
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;
}