Codeforces Round #658 (Div. 2)
阿新 • • 發佈:2020-07-25
A.Common Subsequence
題意
給你兩組數,問你有沒有相同 的書,有的話,輸出最短的那組(大家都知道,1是最小的)
AC
#include<bits/stdc++.h> using namespace std; const int N = 1005; int a[N], x, n, m, flag, t; int main() { //freopen("in.txt","r",stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while (t--) { cin >> n >> m; for (int i = 0; i < n; ++i)cin >> x, a[x]++; flag = 0; for (int i = 0; i < m; ++i) { cin >> x; if (a[x]) flag = x; } if (flag) { cout << "YES" << endl; cout << 1 << " " << flag << endl; } else cout << "NO" << endl; } }
B.Sequential Nim
題意:
兩個人玩區石子游戲,有n堆,第i堆有a[i]個,每個人只能按堆的順序拿,就是前面這堆沒有拿完,不能拿下一堆。誰先不能拿就輸了。
思路:
誰先遇到大於1的石子堆,誰就一定不會輸,因為大於1的石子堆,我可以選擇全拿完和留一個,這兩種狀態結果是互斥的,必定會有一個狀態的必勝態,所以只要判斷到大於1的數前面的1的數量就行,若是全1的情況,那就輪流拿,單獨判斷一下就行。
#include<bits/stdc++.h> using namespace std; int main() { int n, t, x, flag, cnt; //freopen("in.txt", "r", stdin); ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> t; while (t--) { cin >> n; cnt = 0; flag = 0; while (n--) { cin >> x; if (x == 1 && flag == 0) cnt++; if (x > 1) flag = 1; } if ((cnt % 2 == 1 && flag) || (cnt % 2 == 0 && flag == 0)) cout << "Second" << endl; else cout << "First" << endl; } }
C1Prefix Flip (Easy Version)
題意;
給你兩個長度相同的01字串a,b,有一種操作,我們可以把一個字串長度為x的字首拿出來,把0,1互換,(就像是異或一下)然後再把這個字首翻轉(掉個頭)放回到原字串中,問我們通過幾次這種操作把a轉換為b。運算元小於2*n;
思路:
因為我們每次拿的都是字首,那麼也就是說,後面的不會動了,那麼我們可以從後往前來,遇到不同的,就判斷a開頭位置和b當前位置(因為不同就要進行”異或“然後翻轉,會把第一個數翻轉到當前位置上,所以判斷a第一個位置和b當前位置)
如果第一位置和當前位置相同,要把第一位置單獨轉一下,(因為相同,異或再轉過來就不同了)記錄一下每次翻轉的位置就是答案。
#include<bits/stdc++.h>
using namespace std;
int main() {
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
string a, b; int t; cin >> t;
while (t--) {
int n; cin >> n;
cin >> a >> b; int ans = 0;
for (int i = 0; i < n; ++i)if (a[i] != b[i])ans++;
cout << 3 * ans << " ";
for (int i = 0; i < n; ++i)if (a[i] != b[i])cout << i + 1 << " 1 " << i + 1 << " ";
cout << endl;
}
}
C2題待補
D. Unmerge(01揹包問題,1800)
題意:
對於兩個陣列,定義merge運算:每次把兩個陣列的首部的較小的那個拿出,並放到一個新的陣列中。現在給定一個長度為n*2的排列,問你這個排列是否可能由兩個長度為n的陣列merge得到?可能則列印yes,否則no。
思路:
因為每次拿頭部最小的放進新陣列,所以一旦我們碰到一個數值a[i],緊跟a[i]後面的並且小於a[i]的全都應該和a[i]是同一組的,那麼我們對於每次出現的這種,我們記錄它們的長度。如果可能由兩個長度為n的組成,那麼我們可以找到一些長度,他們加起來等於n,也就是01揹包問題了。
#include<bits/stdc++.h>
using namespace std;
const int N = 4e3 + 10;
int dp[N], d[N], a[N];
int main() {
//freopen("in.txt","r",stdin);
ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
int t, n; cin >> t; while (t--) {
cin >> n;
memset(dp, 0, sizeof dp);
for (int i = 1; i <= 2 * n; ++i)cin >> a[i];
int mx = a[1], cnt = 1, len = 0;
for (int i = 2; i <= 2 * n; ++i) {
if (a[i] > mx) {
mx = a[i];
d[++len] = cnt;
cnt = 1;
}
else
cnt++;
}
d[++len] = cnt;
for (int i = 1; i <= len; i++)
for (int j = n; j >= d[i]; j--)
dp[j] = max(dp[j], dp[j - d[i]] + d[i]);
if (dp[n] == n) cout << "YES" << endl;
else cout << "NO" << endl;
}
}