CF系列题解(又是心态炸裂的一场)
Codeforces Round #779 (Div. 2)
题目
A. Marin and Photoshoot
原题链接
题意
给定一个长度为 n n n 的 01 01 01 串,可以添加若干个 1 1 1,使得任意区间内 0 0 0 的个数不超过 1 1 1 的个数。
读题没读明白,还是靠队友才懂,吐了啊。。。
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
1
0
3
)
t (1≤t≤10^3)
t(1≤t≤103) ,表示有t组测试数据。
每个测试数据第一行包含一个个整数
n
(
1
≤
n
≤
100
)
n (1≤n≤100)
n(1≤n≤100) 。
每个测试数据第二行包含一个字符串
s
s
s 。
输出格式
输出需要添加
1
1
1 的个数
输入样例:
9
3
000
3
001
3
010
3
011
3
100
3
101
3
110
3
111
19
1010110000100000101
输出样例:
4
2
1
0
2
0
0
0
17
题解
思路
保证每两个 0 0 0 中间至少有两个 1 1 1 即可。
代码
#include <bits/stdc++.h>
// #define int long long
using namespace std;
typedef long long LL;
void solve()
{
int n;
cin >> n;
string s;
cin >> s;
int ans = 0;
for (int i = 0; i < n; i ++ ) {
if (s[i] == '0') {
int j = i + 1;
while (j < n && s[j] == '1') j ++ ;
if (j < n && j - i - 1 < 2) {
ans += 2 - (j - i - 1);
}
i = j - 1;
}
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
B. Marin and Anti-coprime Permutation
原题链接
B. Marin and Anti-coprime Permutation
题意
求
p
p
p 排列的个数,使得:
g
c
d
(
1
⋅
p
1
,
2
⋅
p
2
,
…
,
n
⋅
p
n
)
>
1
gcd(1⋅p_1,2⋅p_2,…,n⋅p_n)>1
gcd(1⋅p1,2⋅p2,…,n⋅pn)>1
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
1
0
3
)
t (1≤t≤10^3)
t(1≤t≤103) ,表示有t组测试数据。
每个测试数据包含一个整数
n
(
1
≤
n
≤
1
0
3
)
n(1≤n≤10^3)
n(1≤n≤103)。
输出格式
输出排列的个数,由于可能会很大,因此对
998244353
998244353
998244353 取模。
输入样例:
7
1
2
3
4
5
6
1000
输出样例:
0
1
0
4
0
36
665702330
题解
思路
我们假设 g c d = k gcd=k gcd=k , [ 1 , n ] [1,n] [1,n] 中具有因子 k k k 的数有 [ n / k ] [n/k] [n/k] 个,因此原式一共就只有 2 × [ n / k ] 2×[n/k] 2×[n/k] 个因子 k k k ,由于 k > 1 k>1 k>1 ,因此 k k k 只能为 2 2 2 。
因此我们只要把奇数的 p p p 放到 2 , 4 , . . . 2,4,... 2,4,... 之类的偶数上,偶数 p p p 放到 1 , 3 , . . . 1,3,... 1,3,... 之类的奇数上即可,方案数为 ( ( n / 2 ) ! ) 2 ((n/2)!)^2 ((n/2)!)2 。
代码
#include <bits/stdc++.h>
#define int long long
using namespace std;
typedef long long i64;
const int p = 998244353;
void solve()
{
int n;
cin >> n;
if (n % 2) {
cout << "0\n";
return;
}
int ans = 1;
for (int i = n / 2; i; i -- ) {
ans = ans * i % p * i % p;
}
cout << ans << "\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}
C. Shinju and the Lost Permutation
原题链接
C. Shinju and the Lost Permutation
题意
给定一个全排列
p
=
[
p
1
,
p
2
,
…
,
p
n
]
p=[p_1,p_2,…,p_n]
p=[p1,p2,…,pn] ,定义一个操作(不会翻译)
o
p
i
op_i
opi ,使得
p
p
p 变为
p
=
[
p
n
−
i
+
1
,
…
,
p
n
,
p
1
,
p
2
,
…
,
p
n
−
i
]
p=[p_{n−i+1},…,p_n,p_1,p_2,…,p_{n−i}]
p=[pn−i+1,…,pn,p1,p2,…,pn−i] 。
举个栗子:
[
5
,
1
,
2
,
4
,
6
,
3
]
[5,1,2,4,6,3]
[5,1,2,4,6,3] 经过
o
p
0
op_0
op0 变为
[
5
,
1
,
2
,
4
,
6
,
3
]
[5,1,2,4,6,3]
[5,1,2,4,6,3] ,
[
5
,
1
,
2
,
4
,
6
,
3
]
[5,1,2,4,6,3]
[5,1,2,4,6,3] 经过
o
p
1
op_1
op1 变为
[
3
,
5
,
1
,
2
,
4
,
6
]
[3,5,1,2,4,6]
[3,5,1,2,4,6] ,
[
5
,
1
,
2
,
4
,
6
,
3
]
[5,1,2,4,6,3]
[5,1,2,4,6,3] 经过
o
p
2
op_2
op2 变为
[
6
,
3
,
5
,
1
,
2
,
4
]
[6,3,5,1,2,4]
[6,3,5,1,2,4] ,
…
定义全排列
p
p
p 的
m
a
x
max
max 数组为
b
i
=
m
a
x
(
p
1
,
p
2
,
…
,
p
i
)
b_i=max(p_1,p_2,…,p_i)
bi=max(p1,p2,…,pi) ,
p
o
w
e
r
power
power 为
m
a
x
max
max 数组中不同数的个数。
举个栗子:
p
=
[
5
,
1
,
2
,
4
,
6
,
3
]
p=[5,1,2,4,6,3]
p=[5,1,2,4,6,3] ,
b
=
[
5
,
5
,
5
,
5
,
6
,
6
]
b=[5,5,5,5,6,6]
b=[5,5,5,5,6,6] ,
b
b
b 中不同数的个数为
2
2
2 ,因此
p
o
w
e
r
=
2
power=2
power=2 。
p
=
[
3
,
5
,
1
,
2
,
4
,
6
]
p=[3,5,1,2,4,6]
p=[3,5,1,2,4,6] ,
b
=
[
3
,
5
,
5
,
5
,
5
,
6
]
b=[3,5,5,5,5,6]
b=[3,5,5,5,5,6] ,
b
b
b 中不同数的个数为
3
3
3 ,因此
p
o
w
e
r
=
3
power=3
power=3 。
p
=
[
6
,
3
,
5
,
1
,
2
,
4
]
p=[6,3,5,1,2,4]
p=[6,3,5,1,2,4] ,
b
=
[
6
,
6
,
6
,
6
,
6
,
6
]
b=[6,6,6,6,6,6]
b=[6,6,6,6,6,6] ,
b
b
b 中不同数的个数为
1
1
1 ,因此
p
o
w
e
r
=
1
power=1
power=1 。
…
我们定义 c 0 , c 1 , … , c n − 1 c_0,c_1,…,c_{n-1} c0,c1,…,cn−1 数组为全排列 p p p 经过操作 o p i op_i opi 后的得到的排列的 p o w e r power power 值。
给定我们 c 0 , c 1 , … , c n − 1 c_0,c_1,…,c_{n-1} c0,c1,…,cn−1 数组,问我们能否构造出 p p p 。
注:题面太阴间了,因此题主所写题意可能和原题中下标不同,理解题意即可,实在不行看一看样例解释。
输入格式
第一行包含一个整数
t
(
1
≤
t
≤
5
×
1
0
3
)
t (1≤t≤5×10^3)
t(1≤t≤5×103) ,表示有t组测试数据。
每个测试数据第一行包含一个整数
n
(
1
≤
n
≤
1
0
5
)
n(1≤n≤10^5)
n(1≤n≤105) ,表示序列长度。
每个测试数据第二行包含
n
n
n 个整数
c
0
,
c
1
,
…
,
c
n
−
1
(
1
≤
c
i
≤
n
)
c_0,c_1,…,c_{n-1}(1≤c_i≤n)
c0,c1,…,cn−1(1≤ci≤n) 表示给定的序列。
n
n
n 的总和不会超过
1
0
5
10^5
105 。
输出格式
若有满足
c
c
c 的
p
p
p 数组,输出 YES
,否则输出 NO
。
输入样例:
6
1
1
2
1 2
2
2 2
6
1 2 4 6 3 5
6
2 3 1 2 3 4
3
3 2 1
输出样例:
YES
YES
NO
NO
YES
NO
Note:
In the first test case, the permutation
[
1
]
[1]
[1] satisfies the array
c
c
c.
In the second test case, the permutation [ 2 , 1 ] [2,1] [2,1] satisfies the array c c c.
In the fifth test case, the permutation [ 5 , 1 , 2 , 4 , 6 , 3 ] [5,1,2,4,6,3] [5,1,2,4,6,3] satisfies the array c c c. Let’s see why this is true.
- The zeroth cyclic shift of p p p is [ 5 , 1 , 2 , 4 , 6 , 3 ] [5,1,2,4,6,3] [5,1,2,4,6,3]. Its power is 2 2 2 since b = [ 5 , 5 , 5 , 5 , 6 , 6 ] b=[5,5,5,5,6,6] b=[5,5,5,5,6,6] and there are 2 2 2 distinct elements — 5 5 5 and 6 6 6.
- The first cyclic shift of p p p is [ 3 , 5 , 1 , 2 , 4 , 6 ] [3,5,1,2,4,6] [3,5,1,2,4,6]. Its power is 3 3 3 since b = [ 3 , 5 , 5 , 5 , 5 , 6 ] b=[3,5,5,5,5,6] b=[3,5,5,5,5,6].
- The second cyclic shift of p p p is [ 6 , 3 , 5 , 1 , 2 , 4 ] [6,3,5,1,2,4] [6,3,5,1,2,4]. Its power is 1 1 1 since b = [ 6 , 6 , 6 , 6 , 6 , 6 ] b=[6,6,6,6,6,6] b=[6,6,6,6,6,6].
- The third cyclic shift of p p p is [ 4 , 6 , 3 , 5 , 1 , 2 ] [4,6,3,5,1,2] [4,6,3,5,1,2]. Its power is 2 2 2 since b = [ 4 , 6 , 6 , 6 , 6 , 6 ] b=[4,6,6,6,6,6] b=[4,6,6,6,6,6].
- The fourth cyclic shift of p p p is [ 2 , 4 , 6 , 3 , 5 , 1 ] [2,4,6,3,5,1] [2,4,6,3,5,1]. Its power is 3 3 3 since b = [ 2 , 4 , 6 , 6 , 6 , 6 ] b=[2,4,6,6,6,6] b=[2,4,6,6,6,6].
- The fifth cyclic shift of p p p is [ 1 , 2 , 4 , 6 , 3 , 5 ] [1,2,4,6,3,5] [1,2,4,6,3,5]. Its power is 4 4 4 since b = [ 1 , 2 , 4 , 6 , 6 , 6 ] b=[1,2,4,6,6,6] b=[1,2,4,6,6,6].
Therefore, c = [ 2 , 3 , 1 , 2 , 3 , 4 ] c=[2,3,1,2,3,4] c=[2,3,1,2,3,4].
In the third, fourth, and sixth testcases, we can show that there is no permutation that satisfies array c c c.
题解
思路
首先 c c c 数组中肯定存在 c i = 1 c_i=1 ci=1 ,表示原排列 p p p 经过操作 o p i op_i opi 后 p 0 = n p_0=n p0=n ,且 c i = 1 c_i=1 ci=1 只会出现一次。
我们再看一般情况,假设已知 c i c_i ci ,我们能否确定 c i + 1 c_{i+1} ci+1 呢?答案是肯定的。
我们假设经过 o p i op_i opi 后序列为 p 0 , p 1 , p 2 , . . . , p n − 1 p_0,p_1,p_2,...,p_{n-1} p0,p1,p2,...,pn−1 ,我们想要进行操作 o p i + 1 op_{i+1} opi+1 ,实际上就是将我们目前的序列的最后一个数移动到最前面,变为 p n − 1 , p 0 , p 1 , p 2 , . . . , p n − 2 p_{n-1},p_0,p_1,p_2,...,p_{n-2} pn−1,p0,p1,p2,...,pn−2 ,若 p n − 1 < p 0 p_{n-1} <p_0 pn−1<p0 , c i + 1 = c i + 1 c_{i+1}=c_i+1 ci+1=ci+1 ,否则 c i + 1 ≤ c i c_{i+1}≤c_i ci+1≤ci ,证明大家意会一下吧,题主表达能力太弱了不知道怎么说呜呜呜。
因此我们直接从 c i = 1 c_i=1 ci=1 开始往后枚举即可。
大家晕的话可以去看 pzr大佬 。
代码
#include <bits/stdc++.h>
// #define int long long
using namespace std;
constexpr int p = 998244353;
using i64 = long long;
void solve()
{
int n;
cin >> n;
vector<int> c(n);
for (int i = 0; i < n; i ++ ) cin >> c[i];
auto it = find(c.begin(), c.end(), 1);
if (it == c.end()) {
cout << "NO\n";
return;
}
rotate(c.begin(), it, c.end()); // 又从jls哪里学了个函数
for (int i = 1; i < n; i ++ ) {
if (c[i] > c[i - 1] + 1 || c[i] == 1) { // 不能出现两个1
cout << "NO\n";
return;
}
}
cout << "YES\n";
}
signed main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T;
cin >> T;
while (T -- ) {
solve();
}
return 0;
}