A.Common Subsequence
题意:找出两个数组中一个相同的元素。
标记一下出现的数字即可。
int num[1005];
void solve(int T)
{
int a, b;
memset(num, 0, sizeof(num));
cin >> n >> m;
for (int i = 1; i <= n; i++)
{
cin >> a;
num[a] = 1;
}
for (int i = 1; i <= m; i++)
{
cin >> b;
if (num[b] == 1)num[b] = 2;
}
for (int i = 1; i <= 1000; i++)
if (num[i] == 2)
{
cout << "YES\n1 ";
cout << i << endl;
return;
}
cout << "NO\n";
}
B.Sequential Nim
题意:给一堆石子堆,每次只能从最前面的非空的石子堆里取任意石子,无子可取即为输。
我们先看全是1的数组,很显然输赢和数组长度有关。
然后我们把其中一个1换成其他大于1的数字,比如这个样例:
6
1 1 2 1 1 1
如果按照“每人取完当前石子堆”进行游戏,一定是后手赢。我们看,A选手拿完
a
1
a_1
a1,B选手拿完
a
2
a_2
a2,接着,A选手可以选择拿2个或者1个,这将决定比赛输赢。首先确定:我们声明一个数组
b
b
b是以
a
4
a_4
a4开始到
a
n
a_n
an,一定可以确定
b
b
b的唯一赢家,那么如果赢家是先手,A选手就会选择拿1个,让自己成为
b
b
b的先手;否则拿2个,使自己成为后手。
结论:第一个碰到非1的人决定比赛输赢。
int n, k, m;
int a[100005];
void solve(int T)
{
cin >> n;
int pos = -1;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (a[i] != 1 && pos == -1)pos = i;
}
if (pos == -1)if (n % 2 == 0)cout << "Second\n";
else cout << "First\n";
else if (pos % 2 == 1)cout << "First\n";
else cout << "Second\n";
}
C.Prefix Flip
题意:给两个
01
01
01串
a
a
a,
b
b
b。一次操作:选一个
a
a
a的前缀,取反再翻转。问
a
a
a->
b
b
b的每次操作。
先把
a
a
a全部变成
0
0
0或
1
1
1,再从后往前循环
b
b
b数组选择下标位置。
int n, k, m;
vector<int> ans;
void solve(int T)
{
ans.clear();
cin >> n;
string a, b; cin >> a >> b;
for (int i = 1; i < a.size(); i++)
if (a[i] != a[i - 1])
ans.push_back(i - 1);
b[n] = a[n - 1];//a的最后状态取决于a[n-1]
for (int i = n - 1; i >= 0; i--)
if (b[i] != b[i + 1])
ans.push_back(i);
cout << ans.size() << " ";
for (auto x : ans)cout << x + 1 << " ";
cout << endl;
}
D.Unmerge
题意:给两个数组的
m
e
r
g
e
merge
merge规则:如果一个是空数组,结果为另一个数组,否则每次取两个数组中第一位数字较小的。给一个
2
n
2n
2n的序列
p
p
p,问是不是两个数组
m
e
r
g
e
merge
merge之后的结果。
4
3 2 6 1 5 7 8 4
以这个样例举例:
初始状态:
c
1
=
3
c_1=3
c1=3,随便选个数组填上:
c
2
=
2
c_2=2
c2=2,如果放入
b
b
b数组,那么
c
1
c_1
c1应该为
2
2
2而不是
3
3
3,所以放入
a
a
a数组:
c
3
=
6
c_3=6
c3=6,如果继续放入
a
a
a数组,那么之后的1,5也应该是
a
a
a数组的,这时候
a
a
a数组就有5个元素,显然不对,因此放入b。
这时候我们可以断定:3,2来自同一数组。同理,我们得知6,1,5一组,7一组,8,4一组。那么以ab的长度都是
n
n
n为基础,我们把615和7分一组,32和84分一组。
结论:先把
2
n
2n
2n个数分成若干组,再01背包判断选出几组刚好能构成长度为
n
n
n的数组。
int n, k, m;
int a[4005];
vector<int> ans;
int dp[40000];
void solve(int T)
{
memset(dp, 0, sizeof(dp));
ans.clear();
cin >> n;
for (int i = 1; i <= n + n; i++)cin >> a[i];
int tmp = a[1];
int num = 1;
for (int i = 2; i <= n + n; i++)
{
if (a[i] < tmp)num++;
else if (a[i] > tmp)
{
ans.push_back(num);
num = 1;
tmp = a[i];
}
}
ans.push_back(num);
sort(ans.begin(), ans.end());
for (int i = 0; i < ans.size(); i++) {
for (int j = n; j >= ans[i]; j--) {
dp[j] = max(dp[j], dp[j - ans[i]] + ans[i]);
}
}
if (n - dp[n] == 0)cout << "YES\n";//刚好装满
else cout << "NO\n";
}