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;elsecout << "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;}elsecnt++;}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;}}
