Educational Codeforces Round 89

比赛链接 / 官方题解链接

A. Shovels and Swords

Solution

答案是 $\min\left\{\left\lfloor\frac{a+b}{3}\right\rfloor,a,b\right\}$.

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

int T, a, b;

int main(){
for(read(T); T; T--){
read(a, b);
printf("%d\n", min((a + b) / 3, min(a, b)));
}
return 0;
}

B. Shuffle

Solution

能换的下标一定构成一个区间,扫一遍所有操作,如果当前操作与目前的区间有交,就更新区间的左右端点。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const int N = 105;

int T, n, x, m, l[N], r[N];

int main(){
for(read(T); T; T--){
read(n, x, m);
int L = x, R = x;
for(int i = 1; i <= m; i++){
read(l[i], r[i]);
if(l[i] <= R && L <= r[i]){
L = min(L, l[i]);
R = max(R, r[i]);
}
}
printf("%d\n", R - L + 1);
}
return 0;
}

C. Palindromic Paths

Solution

可以证明:所有路径均为回文的充要条件是:对于 $2\leq k\leq n+m$,所有满足 $i+j=k\ 或\ n+m+2-k$ 的 $a[i][j]$ 均相等。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const int N = 35;

int T, n, m, g[N][N];

int main(){
for(read(T); T; T--){
int ans = 0;
read(n, m);
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
read(g[i][j]);
for(int p = 2; p <= n + m; p++){
int q = n + m + 2 - p;
if(p >= q) break;
int cnt[2] = {0};
for(int i = 1; i <= n; i++)
for(int j = 1; j <= m; j++)
if(i + j == p || i + j == q)
cnt[g[i][j]]++;
ans += min(cnt[0], cnt[1]);
}
printf("%d\n", ans);
}
return 0;
}

D. Two Divisors

Solution

分解质因数 $x={p_1}^{r_1}\cdot {p_2}^{r_2}\cdots{p_k}^{r_k}$,则取 $d_1={p_1}^{r_1},\ d_2={p_2}^{r_2}\cdots{p_k}^{r_k}$ 即可。

因为这样,对于 $x$ 的任一质因数 $a$,要么 $a\mid d_1$,要么 $a\mid d_2$,因此 $a\nmid (d_1+d_2)$,于是 $(d_1+d_2)\nmid x$.

那无解的情况就是 $x$ 只有一个质因数。

完成上述操作可以用线性筛,筛出质数的同时得到每个合数的最小质因数。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const int MAX = 10000005;

bool notP[MAX];
int pList[MAX], pID, minDiv[MAX];
void Euler(int n){
notP[0] = notP[1] = 1;
for(int i = 1; i <= n; i++){
if(!notP[i]) pList[++pID] = i;
for(int j = 1; j <= pID; j++){
if(1ll * i * pList[j] > n) break;
notP[i * pList[j]] = 1;
minDiv[i * pList[j]] = pList[j];
if(i % pList[j] == 0) break;
}
}
}

const int N = 500005;

int n;
vector<pii> ans;

int main(){
Euler(10000000);
read(n);
for(int i = 1; i <= n; i++){
int a; read(a);
if(!notP[a]) ans.pb(mp(-1, -1));
else{
int d = minDiv[a];
while(a % d == 0) a /= d;
if(a == 1) ans.pb(mp(-1, -1));
else ans.pb(mp(d, a));
}
}
for(auto &k: ans) printf("%d ", k.first);
puts("");
for(auto &k: ans) printf("%d ", k.second);
return 0;
}

E. Two Arrays

Solution

由于 $b[]$ 单调递增的特点,针对 $a[]$ 开一个单调栈,对这个单调栈进行划分即可。第一划必须在第一个元素之前,对于第二划,找到单调栈中等于 $b[2]$ 的那个区间,设为 $(l,r]$(注意左开右闭),则第二划必须落在这个区间上,总共有 $r$ 对应的位置减去 $l$ 对应的位置那么多划法;后面类似。答案即所有划法之积。

Code

>folded
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
#include<bits/stdc++.h>

using namespace std;

template<typename T>void read(T&x){x=0;int fl=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')
fl=-1;ch=getchar();}while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}x*=fl;}
template<typename T,typename...Args>inline void read(T&t,Args&...args){read(t);read(args...);}

typedef long long LL;
typedef vector<int> vi;
typedef pair<int, int> pii;
#define mp(x, y) make_pair(x, y)
#define pb(x) emplace_back(x)

const int N = 200005;
const LL MOD = 998244353;

int n, m;
LL a[N], b[N];

int main(){
read(n, m);
for(int i = 1; i <= n; i++) read(a[i]);
for(int i = 1; i <= m; i++) read(b[i]);
vector<pii> sta(n+5); int sn = 0;
for(int i = 1; i <= n; i++){
while(sn > 0 && sta[sn].first > a[i]) sn--;
sta[++sn] = mp(a[i], i);
}
if(sta[1].first != b[1]) return puts("0"), 0;
LL ans = 1;
int lst = 0;
for(int i = 2; i <= m; i++){
int l = lst, r = lst;
while(l < sn && sta[l+1].first < b[i]) l++;
if(l == sn) return puts("0"), 0;
while(r < sn && sta[r+1].first <= b[i]) r++;
(ans *= sta[r].second - sta[l].second) %= MOD;
lst = r;
}
printf("%lld\n", ans);
return 0;
}
作者

xyfJASON

发布于

2020-06-12

更新于

2020-12-20

许可协议

评论