Codeforces Round #520 (Div. 2) Solution

A. A Prank

Solved.

题意:

给出一串数字,每个数字的范围是$[1, 1000]$,并且这个序列是递增的,求最多擦除掉多少个数字,使得别人一看就知道缺的数字是什么。

思路:

显然,如果缺的这块数字的个数刚好等于右界 - 左界 + 1 那么就可以知道

还需要考虑数据范围,因为是$<= 1000  和 >= 1$ 那么对于两边的边界需要特殊考虑。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 110
 5 int n, a[N];
 6 
 7 int main()
 8 {
 9     while (scanf("%d", &n) != EOF)
10     {
11         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
12         a[0] = 0; a[n + 1] = 1001;
13         int res = 0, tmp = 1;
14         for (int i = 1; i <= n + 1; ++i)
15         {
16             if (a[i] == a[i - 1] + 1) ++tmp;
17             else
18             {
19                 res = max(res, tmp - 2);
20                 tmp = 1;
21             }
22         }
23         res = max(res, tmp - 2);
24         printf("%d\n", res);
25     }
26     return 0;
27 }
View Code

B. Math

Solved.

题意:

给出一个数$n$, 有两种操作。

第一种是乘上一个任意整数$x$

第二种是开方,并且要保证开方后是整数。

求最少经过多少次操作,可以得到一个最小的数$n$

思路:

考虑$n$的质因数分解形式$a_1^{p_1} \cdot a_2^{p_2} \cdot a_3^{p_3} ...$

那么最小的答案就是$a_1 \cdot a_2 \cdot a_3$

因为一个数开方后是整数的话,显然是每个质因子的幂次都是偶数次,开方相当于每个质因子的幂次 $ / 2$

那么显然每个质因子最小的幂次都是1

再考虑最小的次数,因为乘法可以任意乘一个整数,所以如果需要乘法,那么乘法只需要一次。

再考虑开方,如果质因子中的最高幂次不是2的幂次,那么它不断$ / 2$ 肯定需要至少一次乘法操作,使得可以继续开方下去,直到幂次变为1

那么显然要把幂次变成一个第一个大于等于它的2的幂次数,就可以不断$ / 2$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 2000010
 5 int n, Max, res;
 6 int Bit[N], pos[N];
 7 vector <int> v;
 8 
 9 int solve(int x)
10 {
11     if (x == 1) return 0;
12     if (pos[x] == 0) return 1 + lower_bound(Bit + 1, Bit + 1 + 20, x) - Bit; 
13     for (auto it : v) if (it != x) return 1 + pos[x];
14     return pos[x];
15 }
16 
17 int main()
18 {
19     Bit[0] = 1; pos[1] = 0;  
20     for (int i = 1; i <= 20; ++i)
21     {
22         Bit[i] = Bit[i - 1] << 1;
23         pos[Bit[i]] = i;
24     }    
25     while (scanf("%d", &n) != EOF)
26     {
27         if (n == 1) 
28         {
29             puts("1 0");
30             continue;
31         }
32         v.clear();
33         res = 1; Max = 0;
34         for (int i = 2; i <= n; ++i) 
35         {
36             int tmp = 0; 
37             while (n % i == 0)
38             { 
39                 ++tmp; 
40                 n /= i;
41             }
42             if (tmp) 
43             {
44                 res *= i;
45                 Max = max(Max, tmp);
46                 v.push_back(tmp); 
47             }
48         }    
49         printf("%d %d\n", res, solve(Max));
50     }
51     return 0;
52 }
View Code

C. Banh-mi

Solved.

题意:

给出一个01串,每次询问区间$[l, r]$ 每次可以将区间内一个数取出,并且答案加上这个数的值,区间内剩余的数也加上这个值,求如何安排取出顺序使得答案最大。

思路:

显然1要在0之前取,

我们考虑区间内有$x个1, y 个 0$

那么考虑取出$x个1的答案$

显然 取出的数是形如 1 2 4 8 .....

是一个等比数列,根据求和公式发现答案为$2^x - 1$

再考虑取出的第一个0的数值为 $2^x - 1$

也是一个等比数列,和为 $(2^x - 1) \cdot (2^y - 1)$

合并两项答案   即$2^x \cdot (2^y - 1)$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 const ll MOD = (ll)1e9 + 7;
 7 int n, q, a[N];
 8 
 9 ll qmod(ll base, ll n)
10 {
11     ll res = 1;
12     while (n)
13     {
14         if (n & 1) res = res * base % MOD;
15         base = base * base % MOD;
16         n >>= 1;
17     }
18     return res;
19 }
20 
21 int main()
22 {
23     while (scanf("%d%d", &n, &q) != EOF)
24     {
25         a[0] = 0;
26         for (int i = 1; i <= n; ++i) scanf("%1d", a + i), a[i] += a[i - 1];
27         for (int i = 1, l, r; i <= q; ++i) 
28         {
29             scanf("%d%d", &l, &r);
30             int x = a[r] - a[l - 1], y = (r - l + 1) - x;
31             if (x == 0) 
32             {
33                 puts("0");
34                 continue;
35             }
36             printf("%lld\n", qmod(2, y) * (qmod(2, x) - 1 + MOD) % MOD);
37         }
38     }
39     return 0;
40 }
View Code

D. Fun with Integers

Solved.

题意:给出一个数$n$,任意$|a| , |b| < n$ 并且满足 $|a| |b| 互为倍数关系$ 那么答案加上这个倍数,并且这一对$|a|, |b|$不再提供贡献,并且倍数关系$|x| > 1$

思路:

考虑一个数$x$, 那么在$[1, n]$ 中是它的倍数的数一共有 $y = \lfloor \frac {n}{x} \rfloor \cdot 2$ 个 因为还有负的

那么这个数的贡献是$\sum_2 ^y  \cdot 2$ 再考虑 $-x$ 也会提供一样的贡献 即答案要乘2

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 int n;
 6 
 7 int main()
 8 {
 9     while (scanf("%d", &n) != EOF)
10     {
11         ll res = 0;
12         for (int i = 2; i <= n; ++i)
13         {
14             ll x = n / i;
15             res += 2ll * (x + 2) * (x - 1);
16         }
17         printf("%lld\n", res);
18     }
19     return 0;
20 }
View Code

E. Company

Unsolved.

题意:

在一棵树中,每次选择一个区间$[l, r]$ 最多删除一个点,使得这个区间内所有点的$lca$ 的深度最大。

F. Upgrading Cities

Unsolved.

猜你喜欢

转载自www.cnblogs.com/Dup4/p/9961478.html