题解
第一题
因为每次只拿两个,所以不改变原来序列的奇偶性。
所以直接判断奇偶性即可。
#include <bits/stdc++.h>
using namespace std;
int main()
{
int N; scanf("%d", &N);
if(N % 2 == 0) puts("Yitong_Qin");
else puts("Xiaoyu_Chen");
return 0;
}
第二题
我们可以将字符串
S
N
S
N
−
1
.
.
.
S
0
S_NS_{N-1}...S_0
SNSN−1...S0视为由
S
N
−
1
.
.
.
S
0
S_{N-1}...S_0
SN−1...S0在前方补
S
N
S_N
SN得到的。
也就是说,可以先得到
S
N
−
1
.
.
.
S
0
S_{N-1}...S_0
SN−1...S0的消去情况,再在前面补充一个字符考虑能否消去。
由题意:只要不同的字符相邻且不同,必然可以完成一次消去。从而尽可能完成消去操作后,最后剩余的字符串必然是由一串相同的字符构成。
我们假设 S N − 1 . . . S 0 S_{N-1}...S_0 SN−1...S0消去后得到的字符串由若干个相同的字符 S S S 构成。假设我们在前方增加了一个字符 S N S_N SN,只有两种可能:
- 当 S N S_N SN 和 S S S 相同时,不能执行消去操作,字符串长度加一
- 当 S N S_N SN 和 S S S 不同时,由于 S N S_N SN在前,消去后仍然是 S N S_N SN,而后面的字符 S S S个数将减少1。重复这一步骤,会使得字符串变成一个单独的 S N S_N SN.此时字符串长度为1。
从而我们可以倒着从后往前找一遍。如果两个相邻的字符相同word[i] == word [i + 1]
,那么字符串长度就应该加一,也就是ans[i] = ans[i + 1] + 1
,如果不同,则字符串将消为当前位置的字符,消去后字符串长度为1,也就是ans[i] = 1
。
最后我们输出消至首位的ans[0]
即为解。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 200000 + 10;
char word[MAXN];
int ans[MAXN];
int main()
{
scanf("%s", word);
int len = strlen(word);
ans[len - 1] = 1;
for(int i = len - 2;i >= 0; --i)
{
if(word[i] == word [i + 1])
ans[i] = ans[i + 1] + 1;
else
ans[i] = 1;
}
printf("%d\n", ans[0]);
return 0;
}
第三题
首先,如果 X X X个 7 7 7 可以凑24点,则 ( X + 2 ∗ K ) (X + 2 * K) (X+2∗K)个 7 7 7 也可以,只需要在原来的式子后面乘上 ( 7 / 7 ) (7 / 7) (7/7) 就可以了(因为 24 ∗ 1 = 24 24 * 1 = 24 24∗1=24)
然后最小成立的奇数个数是7个7,方案是:
7
+
7
+
7
+
(
7
+
7
+
7
)
/
7
=
21
+
3
=
24
7 + 7 + 7 + (7 + 7 + 7) / 7 = 21 + 3 = 24
7+7+7+(7+7+7)/7=21+3=24
最小成立的偶数个数是6个7。
(
7
∗
7
∗
7
−
7
)
/
(
7
+
7
)
=
(
7
∗
48
)
/
(
7
∗
2
)
=
24
(7 * 7 * 7 - 7) / (7 + 7) = (7 * 48) / (7 * 2) = 24
(7∗7∗7−7)/(7+7)=(7∗48)/(7∗2)=24
所以大于等于6时必然有解。
#include<bits/stdc++.h>
using namespace std;
int main()
{
int N; cin >> N;
if(N >= 6) puts("YES");
else puts("NO");
return 0;
}
第四题
序列要么是 101010…这样的,要么是 010101…这样的。
我们先讨论一下如何把原序列变成 101010… 这样的序列。
-
首先,分析我们可以进行两种操作,要么把两个人交换位置,要么把一个人改变属性。考虑到对具体某个人来说,他只存在两种情况,要么站对了位置要么站错了,站对位置的人我们没必要动他,所以我们只需要讨论那些站错了位置的,也就是这个位置应该站0却站了个1这样子。
-
然后我们发现,对一对站错位置的1和0来说,我们交换他们只需要1次,但分别改变他们却需要2次。也就是说,我们应该尽可能地交换他们。但是站错位置的1和0数量不一定一样,我们尽可能交换完之后,可能还会剩下一些站错位置的人,他们没有可以交换的人了。这时我们只能手动改变他们。
-
记站错位置的 1 1 1有 A A A 个, 0 0 0有 B B B 个,不妨设 A > B A>B A>B, 则需要交换 B B B次,此时还有 A − B A - B A−B个 1 1 1没被处理,因此还需要手动改变 A − B A - B A−B次,也就是总共需要 B + ( A − B ) = A B + (A - B) = A B+(A−B)=A次。当 B > A B>A B>A时类似,可知需要 B B B次。综上,需要次数为 m a x ( A , B ) max(A, B) max(A,B)次。
-
010101…的处理方法类似。
我们记改变为101010…的次数为M次,改变成010101…的次数为N次,
那么肯定哪个小选哪个,于是需要次数为
m
i
n
(
M
,
N
)
min(M, N)
min(M,N)次。
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100000 + 10;
int N; char Drivers[MAXN];
int place_1010[2], place_0101[2];
int ans;
void pre()
{
cin >> N;
scanf("%s", Drivers);
for(int i = 0;i < N; ++i)
{
if(i % 2 == 0)
{
if(Drivers[i] == '1') ++place_1010[1];
else ++place_0101[0];
}
else
{
if(Drivers[i] == '1') ++place_0101[1];
else ++place_1010[0];
}
}
}
int main()
{
pre();
ans = min( max(place_1010[0], place_1010[1]), max(place_0101[0], place_0101[1]));
cout << ans << endl;
return 0;
}
第五题
考虑三种情况。
-
自己只有一张牌
- 必然胜利,出完就没了。
-
自己有两张牌。
- 考虑到对方如果小于等于2张,必须先压制对方的最大牌
- 此时出完最大牌之后不能被对方压制,一旦对方比自己最大牌大就输了
- 对方牌比2张多,此时考虑到不论自己出小的还是大的对方都要压制己方最大牌
- 于是只需要自己小牌比对方第二小的牌大即可
- 考虑到对方如果小于等于2张,必须先压制对方的最大牌
#include<bits/stdc++.h>
using namespace std;
const char poker[20] = { '3', '4', '5', '6', '7', '8',
'9', 'T', 'J', 'Q', 'K', 'A', '2'};
int find(char ch)
{
for(int i = 0;i < 13; ++i)
if(ch == poker[i]) return i + 1;
}
const int MAXN = 20;
char ss1[MAXN], ss2[MAXN];
int pk1[MAXN], pk2[MAXN];
int len1, len2;
void pre()
{
scanf("%s", ss1);scanf("%s", ss2);
len1 = strlen(ss1); len2 = strlen(ss2);
for(int i = 0;i < len1; ++i) pk1[i] = find(ss1[i]);
for(int i = 0;i < len2; ++i) pk2[i] = find(ss2[i]);
return;
}
bool ok()
{
if(len1 == 1) return true;
if(len2 <= 2)
{
if(pk1[1] >= pk2[len2 - 1]) return true;
else return false;
}
if(pk2[1] < pk1[1]) return true;
return false;
}
int main()
{
pre();
if(ok()) cout << "zhong_wang" << endl;
else cout << "cfeitong" << endl;
return 0;
}