A. Indirect Sort
题意:
给出一个长度为
n
n
n 的排列
a
a
a,同时定义一种操作:
选择三个下标
i
、
j
、
k
,
(
1
≤
i
≤
j
≤
k
≤
n
)
i、j、k,(1\leq i\leq j\leq k\leq n)
i、j、k,(1≤i≤j≤k≤n);
如果
a
i
>
a
k
a_i >a_k
ai>ak ,用
a
i
+
a
j
a_i+a_j
ai+aj 来替换原先
a
i
a_i
ai ,否则交换
a
j
a_j
aj 和
a
k
a_k
ak 。
问是否可以操作任意次使
a
a
a 变为一个非递减序列(非排列)。
思路:
都是 A A A 题了还能有啥难度,通过观察样例可以联想到,当 a 1 ≠ 1 a_1\neq1 a1=1 时,无论怎样操作都无法改变 a i = 1 a_i=1 ai=1,而且 a i a_i ai 永远比 1 1 1 大。
时间复杂度: O ( 1 ) O(1) O(1)
int n, m;
int s[N];
signed main() {
IOS
cf{
sf(n);
for (int i = 1; i <= n; i++)
sf(s[i]);
if (s[1] == 1)
pfn("Yes");
else
pfn("No");
}
return 0;
}
B. Maximum Substring
题意:
给出一个 01 01 01 字符串 s s s,对于包含 x x x 个 0 0 0 和 y y y 个 1 1 1 的字符串 s s s 的非空子字符串 t t t,将其价值定义为:
- x ∗ y x*y x∗y 如果 x > 0 & & y > 0 x>0\&\&y>0 x>0&&y>0
- x 2 x^2 x2 如果 x > 0 & & y = 0 x>0\&\&y=0 x>0&&y=0
-
y
2
y^2
y2 如果
x
=
0
&
&
y
>
0
x=0\&\&y>0
x=0&&y>0
求字符串 s s s 的所有非空子字符串 t t t的最大价值。
思路:
第一种价值的最大值肯定是 s s s 本身,而剩下两种只需要找到 s s s 中所有连续相同字符的最大长度即可求出。
时间复杂度: O ( n ) O(n) O(n)
int n, m;
char s[N];
signed main() {
IOS
cf{
sf(n);
sf(s + 1);
int a = 0, b = 0;
for (int i = 1; i <= n; i++)
if (s[i] == '0')
a++;
else
b++;
int ans = a * b, j = 1;
for (int i = 2; i <= n; i++)
if (s[i] == s[i - 1])
j++;
else {
ans = max(ans, j * j);
j = 1;
}
ans = max(ans, j * j);
pfn(ans);
}
return 0;
}
C. Complementary XOR
题意:
给两个长度为 n n n 的 01 01 01 字符串 a , b a,b a,b,并定义一种操作:
- 首先选择两个下标 l , r , ( 1 ≤ l ≤ r ≤ n ) l,r,(1\leq l\leq r\leq n) l,r,(1≤l≤r≤n)
- 将 a i a_i ai 变为 1 − a i 1-a_i 1−ai, ( 1 ≤ i ≤ r ) (1\leq i\leq r) (1≤i≤r)
- 将
b
i
b_i
bi 变为
1
−
b
i
1-b_i
1−bi,
(
1
≤
i
<
l
∣
∣
r
<
i
≤
n
)
(1\leq i<l ||r<i\leq n)
(1≤i<l∣∣r<i≤n)
问是否能够通过 ≤ n + 5 \leq n+5 ≤n+5 次操作使字符串 a , b a,b a,b 都变为 0 0 0 ,如果可以的话输出所有操作,否则输出 N O NO NO。
思路:
这道题我的思路太码了,就不细说了,推荐搜索其他人的题解。
时间复杂度: O ( n ) O(n) O(n)
int n, m;
char a[N], b[N];
signed main() {
IOS
cf{
sf(n);
sf(a + 1), sf(b + 1);
int v0 = 0, v1 = 0;
bool st1 = true, st2 = true;//1相同,2不同
for (int i = 1; i <= n; i++) {
if (a[i] == b[i])
st2 = false;
else
st1 = false;
if (a[i] == '0')
v0++;
else
v1++;
}
if ((st1 || st2) == false) {
pfn("NO");
continue;
}
vector<PII> ans1, ans0;
for (int i = 1; i <= n; i++)
if (a[i] == '1')
ans1.push_back({i, i});
else
ans0.push_back({i, i});
if (st1 && v1 % 2 == 0) {
pfn("YES");
pfn(ans1.size());
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
if (st1 && v0 % 2 == 1) {
pfn("YES");
pfn(ans0.size() + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v0 % 2 == 0) {
pfn("YES");
pfn(ans0.size() + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v1 % 2 == 1) {
pfn("YES");
pfn(ans1.size());
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
int j = -1;
for (int i = 1; i < n; i++)
if (a[i] == a[i + 1]) {
j = i;
break;
}
if (j != -1) {
if (a[j] == '1')
v1 -= 2, v0 += 2;
else
v0 -= 2, v1 += 2;
st1 = !st1;
st2 = !st2;
a[j] = 1 - (a[j] - '0') + '0';
a[j + 1] = 1 - (a[j + 1] - '0') + '0';
ans1.clear(), ans0.clear();
for (int i = 1; i <= n; i++)
if (a[i] == '1')
ans1.push_back({i, i});
else
ans0.push_back({i, i});
if (st1 && v1 % 2 == 0) {
pfn("YES");
pfn(ans1.size() + 1);
pp(j, j + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
if (st1 && v0 % 2 == 1) {
pfn("YES");
pfn(ans0.size() + 1 + 1);
pp(j, j + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v0 % 2 == 0) {
pfn("YES");
pfn(ans0.size() + 1 + 1);
pp(j, j + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v1 % 2 == 1) {
pfn("YES");
pfn(ans1.size() + 1);
pp(j, j + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
} else {
st1 = !st1;
st2 = !st2;
a[1] = 1 - (a[1] - '0') + '0';
a[1 + 1] = 1 - (a[1 + 1] - '0') + '0';
j = 2;
if (a[j] == '1')
v1 -= 2, v0 += 2;
else
v0 -= 2, v1 += 2;
st1 = !st1;
st2 = !st2;
a[j] = 1 - (a[j] - '0') + '0';
a[j + 1] = 1 - (a[j + 1] - '0') + '0';
ans1.clear(), ans0.clear();
for (int i = 1; i <= n; i++)
if (a[i] == '1')
ans1.push_back({i, i});
else
ans0.push_back({i, i});
if (st1 && v1 % 2 == 0) {
pfn("YES");
pfn(ans1.size() + 1 + 1);
pp(1, 2);
pp(j, j + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
if (st1 && v0 % 2 == 1) {
pfn("YES");
pfn(ans0.size() + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v0 % 2 == 0) {
pfn("YES");
pfn(ans0.size() + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v1 % 2 == 1) {
pfn("YES");
pfn(ans1.size() + 1 + 1);
pp(1, 2);
pp(j, j + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
int jj = -1;
for (int i = 1; i < n; i++)
if (a[i] == a[i + 1]) {
jj = i;
break;
}
if (a[jj] == '1')
v1 -= 2, v0 += 2;
else
v0 -= 2, v1 += 2;
st1 = !st1;
st2 = !st2;
a[jj] = 1 - (a[jj] - '0') + '0';
a[jj + 1] = 1 - (a[jj + 1] - '0') + '0';
ans1.clear(), ans0.clear();
for (int i = 1; i <= n; i++)
if (a[i] == '1')
ans1.push_back({i, i});
else
ans0.push_back({i, i});
if (st1 && v1 % 2 == 0) {
pfn("YES");
pfn(ans1.size() + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
pp(jj, jj + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
if (st1 && v0 % 2 == 1) {
pfn("YES");
pfn(ans0.size() + 1 + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
pp(jj, jj + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v0 % 2 == 0) {
pfn("YES");
pfn(ans0.size() + 1 + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
pp(jj, jj + 1);
for (auto i : ans0)
pp(i.x, i.y);
pp(1, n);
continue;
}
if (st2 && v1 % 2 == 1) {
pfn("YES");
pfn(ans1.size() + 1 + 1 + 1);
pp(1, 2);
pp(j, j + 1);
pp(jj, jj + 1);
for (auto i : ans1)
pp(i.x, i.y);
continue;
}
}
}
return 0;
}
D. Count GCD
题意:
给出两个数
n
,
m
n,m
n,m 以及一个正整数序列
a
,
(
1
≤
a
i
≤
m
,
1
≤
i
≤
n
)
a,(1\leq a_i\leq m,1\leq i\leq n)
a,(1≤ai≤m,1≤i≤n)。
你需要构造正整数序列
b
b
b ,使其满足两个条件:
- 1 ≤ b i ≤ m , ( 1 ≤ i ≤ n ) 1\leq b_i\leq m,(1\leq i\leq n) 1≤bi≤m,(1≤i≤n)
-
g
c
d
(
b
1
,
b
2
,
…
…
b
i
−
1
,
b
i
)
=
a
i
,
(
1
≤
i
≤
n
)
gcd(b_1,b_2,……b_{i-1},b_i)=a_i,(1\leq i\leq n)
gcd(b1,b2,……bi−1,bi)=ai,(1≤i≤n)
问符合条件的 b b b 有多少个,结果对 998244353 998244353 998244353 取模。
思路:
有一说一,这道题比 C C C 简单多了,浪费时间……
首先非法的情况很好考虑,如果序列 a a a 本身都不符合条件直接返回 0 0 0 。
接下来就是问遍历到
i
i
i 时,有多少个数
x
x
x 满足
g
c
d
(
a
i
−
1
,
x
)
=
a
i
gcd(a_{i-1},x)=a_i
gcd(ai−1,x)=ai 。
因为
a
i
∣
a
i
−
1
a_i|a_{i-1}
ai∣ai−1 ,如果
a
i
=
=
a
i
−
1
a_i==a_{i-1}
ai==ai−1 ,那么
1
−
m
1-m
1−m 中所有
a
i
a_i
ai 的倍数均可以;否则,符合条件的数为
1
−
m
1-m
1−m 中所有
a
i
a_i
ai 的倍数并且与
a
i
−
1
a
i
\frac{a_{i-1}}{a_i}
aiai−1 互质的所有数。
后面那个限制条件看上去是不是很熟悉?就是容斥原理的板子。
时间复杂度: O (暴力,但是能过) O(暴力,但是能过) O(暴力,但是能过)
int n, m;
int s[N];
int get(int u, int al) {
vector<int> p;
for (int i = 2; i <= u / i; i++)
if (u % i == 0) {
p.push_back(i);
while (u % i == 0)
u /= i;
}
if (u > 1)
p.push_back(u);
int res = 0;
int len = p.size();
for (int i = 1; i < (1ll << len); i++) {
int cnt = 0, t = 1;
for (int j = 0; j < len; j++)
if (i >> j & 1) {
cnt++;
if (t * p[j] > al) {
t = -1;
break;
}
t *= p[j];
}
if (t != -1) {
if (cnt % 2)
res += al / t;
else
res -= al / t;
}
}
return res;
}
signed main() {
IOS
cf{
sf2(n, m);
for (int i = 1; i <= n; i++)
sf(s[i]);
int tmp = s[1];
bool flag = true;
for (int i = 2; i <= n; i++) {
tmp = __gcd(tmp, s[i]);
if (tmp != s[i]) {
flag = false;
break;
}
}
if (flag == false) {
pfn("0");
continue;
}
int ans = 1;
tmp = s[1];
for (int i = 2; i <= n; i++) {
if (tmp == s[i]) {
ans = ans * (m / s[i]) % mod;
} else {
int cnt = m / s[i];
cnt -= get(tmp / s[i], m / s[i]);
ans = ans * cnt % mod;
tmp = s[i];
}
}
pfn(ans);
}
return 0;
}