codeforces Educational Round 89


A、Shovels and Swords

题意:

两个木棍一个钻石做一把钻石铲,一个木棍两个钻石做一把钻石剑,现在有$a$个木棍,$b$各位钻石,求最多能做多少钻石工具?

题解:

如果两个恰好用完,直接列方程组求解得$\frac {a+b}{3}$,如果有一种东西剩下来了,那么答案就是另一个的数量,所以最终的答案是$min(\frac {a+b}{3}, a, b)$。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 5;
 4 typedef long long ll;
 5 typedef pair<int, int> pii;
 6 void solve()
 7 {
 8     int a, b;
 9     scanf("%d%d", &a, &b);
10     printf("%d\n", min((a + b) / 3, min(a, b)));
11 }
12 int main()
13 {
14     int T;
15     scanf("%d", &T);
16     while (T--)
17         solve();
18     return 0;
19 }
View Code

B、Shuffle

题意:

给出一个数组长度是$n$,其中$a_x$是$1$,其他都是$0$,给出$m$个操作,每个操作给出我范围$l$,$r$,你可以任意选择两个范围内的位置,可以是一样的位置,然后交换其值,求这$m$个操作结束后,有多少个位置的值是可以变成$1$的。

题解:

首先之前的操作结束后,只要$1$可能到达的位置范围和这次询问的范围有交集,那么显然这次操作的整个范围$1$都是可达的,所以如果之前$1$可以到达的范围和这次操作的范围有交集,则可达范围变成这两个范围的并集,如果没有交集则直接丢弃。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 5;
 4 typedef long long ll;
 5 typedef pair<int, int> pii;
 6 void solve()
 7 {
 8     int n, x, m;
 9     scanf("%d%d%d", &n, &x, &m);
10     int ql, qr, l, r;
11     ql = qr = x;
12     for (int i = 1; i <= m; ++i)
13     {
14         scanf("%d%d", &l, &r);
15         if (ql > r || qr < l)
16             continue;
17         ql = min(ql, l);
18         qr = max(qr, r);
19     }
20     printf("%d\n", qr - ql + 1);
21 }
22 int main()
23 {
24     int T;
25     scanf("%d", &T);
26     while (T--)
27         solve();
28     return 0;
29 }
View Code

C、Palindromic Paths

题意:

给出一个$01$矩阵,一个人从$(1,1)$出发到达$(n,m)$,只能向右或者向下。他走过地方(包括起点终点)会形成一个$01$串,求最少改变多少个位置,使得这个人走过的所有路径形成的串都是回文串。

题解:

我们画出矩阵中走到某一步可能的位置发现:$i+j=const$,所以为了保证回文,所以正数第$k$步和倒数第$k$步的所有字符都必须一样。这样子我们就可以开个桶,统计$1$的数量,然后就可以顺便推出$0$的数量,取小的值加到答案中。然后注意到,如果路径长度是奇数,那么最中间的一步的字符是任意的,如果是偶数,那么最中间的两步的字符也一定要一样。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N = 1e5 + 5;
 4 typedef long long ll;
 5 typedef pair<int, int> pii;
 6 int buc[105];
 7 void solve()
 8 {
 9     memset(buc, 0, sizeof(buc));
10     int n, m, a;
11     scanf("%d%d", &n, &m);
12     for (int i = 1; i <= n; ++i)
13         for (int j = 1; j <= m; ++j)
14         {
15             scanf("%d", &a);
16             buc[i + j] += a;
17         }
18     int ans = 0;
19     for (int i = 2; i <= (n + m) / 2; ++i)
20     {
21         int one = buc[i] + buc[n + m - i + 2];
22         int size;
23         if (i <= min(n, m))
24             size = (i - 1) * 2;
25         else
26             size = min(n, m) * 2;
27         ans += min(one, size - one);
28     }
29     if ((n + m) % 2 == 1)
30     {
31         int size = min(n, m) * 2;
32         int one = buc[(n + m) / 2 + 1] + buc[(n + m) / 2 + 2];
33         ans += min(one, size - one);
34     }
35     printf("%d\n", ans);
36 }
37 int main()
38 {
39     int T;
40     scanf("%d", &T);
41     while (T--)
42         solve();
43     return 0;
44 }
View Code

D、Two Divisors

题意:

给出$n$个数,对每个数$a_i$,求出一个$pair(d_1,d_2)$,满足$d_1>1$且$d_2>1$且$gcd(d_1+d_2,a_i)=1$,或者输出$(-1,-1)$表示没有。

题解:

解法一:

考虑$gcd$的性质:$gcd(d_1,d_2) = 1$,则$gcd(d_1 \times d_2, d_1+d_2) = gcd(d_1,d_1+d_2)\times gcd(d_2,d_1+d_2) = 1$,所以我们暴力地找即可。显然,这个$a_i$是素数的时候或者只有一个质因数,一定找不到。

AC代码(加上了记忆化):

 1 #include <bits/stdc++.h>
 2 #include <unordered_map>
 3 using namespace std;
 4 const int N = 5e5 + 5;
 5 typedef long long ll;
 6 typedef pair<int, int> pii;
 7 const int M = 1e7 + 5;
 8 bool isp[M];
 9 int p[M], tot;
10 void init()
11 {
12     memset(isp, 0x3f, sizeof(isp));
13     for (int i = 2; i < M; ++i)
14     {
15         if (isp[i])
16             p[++tot] = i;
17         for (int j = 1; j <= tot && p[j] * i < M; ++j)
18         {
19             isp[p[j] * i] = 0;
20             if (i % p[j] == 0)
21                 break;
22         }
23     }
24 }
25 int a[N];
26 pii ans[N];
27 int fac[N], top;
28 int n = 1000;
29 int gcd(int a, int b)
30 {
31     return !b ? a : gcd(b, a % b);
32 }
33 pii get_fac(int x)
34 {
35     for (int i = 2; i * i <= x; ++i)
36         if (x % i == 0 && gcd(i, x / i) == 1)
37             return {i, x / i};
38     return {-1, -1};
39 }
40 unordered_map<int, pii> mp;
41 void solve()
42 {
43     scanf("%d", &n);
44     for (int i = 1; i <= n; ++i)
45         scanf("%d", &a[i]);
46     for (int i = 1; i <= n; ++i)
47     {
48         if (isp[a[i]])
49             ans[i] = {-1, -1};
50         else
51         {
52             if (mp.find(a[i]) == mp.end())
53             {
54                 get_fac(a[i]);
55                 if (top == 1)
56                     ans[i] = {-1, -1};
57                 else
58                     ans[i] = get_fac(a[i]);
59                 mp[a[i]] = ans[i];
60             }
61             else
62                 ans[i] = mp[a[i]];
63         }
64     }
65     for (int i = 1; i <= n; ++i)
66         printf("%d%c", ans[i].first, " \n"[i == n]);
67     for (int i = 1; i <= n; ++i)
68         printf("%d%c", ans[i].second, " \n"[i == n]);
69 }
70 int main()
71 {
72     init();
73     int T = 1;
74     //scanf("%d", &T);
75     while (T--)
76         solve();
77     return 0;
78 }
View Code

解法二:

上面的$gcd$性质有点难想,我们可以换个想法,设$p_1$是$a_i$最小的质因数,设$a_i=x\times p_1^k$,我们令$d_1=p_1^k,d2=x$,如果其中一个是$1$就是找不到,素数也找不到。正确性显然。

注:代码中的欧拉筛是完整功能的欧拉筛,$pm[i]$是$i$的最小质因子,$pk[i]$是这个最小质因子的幂次$k$,满足$i\%pm[i]^k==0$且$i\%pm[i]^{k+1}!=0$。

AC代码(加上了记忆化):

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef pair<int, int> pii;
 4 const int M = 1e7 + 5;
 5 const int N = 5e5 + 5;
 6 bool isp[M];
 7 int p[M], pm[M], ps[M];
 8 int tot;
 9 void get_p()
10 {
11     memset(isp, 0xff, sizeof(isp));
12     for (int i = 2; i < M; ++i)
13     {
14         if (isp[i])
15             p[++tot] = pm[i] = ps[i] = i;
16         for (int j = 1; j <= tot; ++j)
17         {
18             int tmp = i * p[j];
19             if (tmp >= M)
20                 break;
21             isp[tmp] = 0;
22             pm[tmp] = p[j];
23             if (i % p[j])
24                 ps[tmp] = p[j];
25             else
26             {
27                 ps[tmp] = ps[i] * p[j];
28                 break;
29             }
30         }
31     }
32 }
33 int a[N];
34 pii ans[N];
35 void solve()
36 {
37     get_p();
38     int n;
39     scanf("%d", &n);
40     for (int i = 1; i <= n; ++i)
41         scanf("%d", &a[i]);
42     for (int i = 1; i <= n; ++i)
43     {
44         if (isp[a[i]] || a[i] == ps[a[i]])
45             ans[i] = { -1,-1 };
46         else
47         {
48             int tmp = a[i];
49             ans[i].first = pm[tmp];
50             tmp /= ps[tmp];
51             ans[i].second = 1;
52             while (tmp != 1)
53             {
54                 ans[i].second *= pm[tmp];
55                 tmp /= ps[tmp];
56             }
57         }
58     }
59     for (int i = 1; i <= n; ++i)
60         printf("%d%c", ans[i].first, " \n"[i == n]);
61     for (int i = 1; i <= n; ++i)
62         printf("%d%c", ans[i].second, " \n"[i == n]);
63 }
64 int main()
65 {
66     int T = 1;
67     //scanf("%d", &T);
68     while (T--)
69         solve();
70     return 0;
71 }
View Code

E、Two Arrays

题意:

题解:

AC代码:

 

posted @ 2020-06-12 21:15  Aya_Uchida  阅读(225)  评论(0编辑  收藏  举报