Educational Codeforces Round 57 Solution

A. Find Divisible

签到。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t, l, r;
 5 
 6 int main()
 7 {
 8     scanf("%d", &t);
 9     while (t--)
10     {
11         scanf("%d%d", &l, &r);
12         printf("%d %d
", l, l * 2);
13     }
14     return 0;
15 }
View Code

B. Substring Removal

签到。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 200010
 6 const ll MOD = 998244353;
 7 int len;
 8 char s[N];
 9 
10 ll f(ll x) { return x * (x + 1) / 2; } 
11 
12 int main()
13 {
14     while (scanf("%d", &len) != EOF) 
15     {
16         scanf("%s", s + 1);
17         int l, r;
18         for (l = 2; l <= len; ++l) if (s[l] != s[l - 1])
19             break;
20         for (r = len - 1; r >= 1; --r) if (s[r] != s[r + 1])
21             break;
22         ll res;
23         r = len - r + 1;
24         if (s[1] == s[len]) 
25             res = min(f(len), 1ll * l * r);
26         else 
27             res = min(f(len), 1ll * l + r - 1);
28         printf("%lld
", res % MOD);    
29     }
30     return 0;
31 }
View Code

C. Polygon for the Angle

Solved.

题意:

问在一个正n多边形中任意三点构成的角的集合中包含ang的最小的n是多少

思路:

一个正$n多边形每个角的大小是 x = 180 - frac{360}{n}$

我们考虑点可以怎么选,如果中间的点固定,两边的点往两边走的话

我们可以发现单侧的一条边和单侧会构成一个多边形

这个多边形有$k个角,但是有k - 2个角都是x,并且剩下的两个角相等$

这样就可以算出选的点往两边扩展会减去的角的大小

我们发现,两个点往两边扩展分别构成的多边形的点数为$k, o$

那么 $k + o <= n + 1$

那么通过整理我们发现一个多边形可以构成的角的集合为

$180 - (180 - (j - 2)) / n ;; j in [4, n + 1]$

而且我们发现 当$n = 180 的时候可以构成[1, 179]种的任意角,那么遍历一下,遍历到180预处理一下答案即可$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t, n;
 5 int ans[200]; 
 6 
 7 int main()
 8 {
 9     memset(ans, -1, sizeof ans);
10     for (int i = 360; i >= 1; --i) for (int j = 4; j <= i + 1; ++j) if ((180 * (j - 2) % i) == 0)
11     {
12         int x = 180 - (180 * (j - 2)) / i;
13         ans[x] = i;
14     }
15     scanf("%d", &t);
16     while (t--)
17     {
18         scanf("%d", &n);
19         printf("%d
", ans[n]);    
20     }
21     return 0;
22 }
View Code

D. Easy Problem

Upsolved.

题意:

给处一个字符串,有权,求移除一些字符使得花费最少并且没有一个子序列构成'hard'

思路:

我们发现只要断掉一种字符的路就可以了

那么对于'h' 要断掉它的路就必然要去掉所有的'h'

但是对于'a', 'r', 'd' 这三种字符来说,断掉他们的路,可以选择去掉当前

遇到的字符,或者去掉前面所有在他们前面位置的那个字符

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 100010
 6 int n; ll dp[N];
 7 char s[N];
 8 
 9 int main()
10 {
11     while (scanf("%d", &n) != EOF)
12     {
13         scanf("%s", s + 1);
14         memset(dp, 0x3f, sizeof dp);
15         dp[0] = 0;
16         for (int i = 1, a; i <= n; ++i)
17         {
18             scanf("%d", &a);
19             if (s[i] == 'h')
20             {
21                 dp[1] = min(dp[1], dp[0]);
22                 dp[0] += a;
23             }
24             else if (s[i] == 'a')
25             {
26                 dp[2] = min(dp[2], dp[1]);
27                 dp[1] += a;
28             }
29             else if (s[i] == 'r')
30             {
31                 dp[3] = min(dp[3], dp[2]);
32                 dp[2] += a;
33             }
34             else if (s[i] == 'd')
35                 dp[3] += a;    
36         }
37         printf("%lld
", *min_element(dp, dp + 4));
38     }
39     return 0;
40 }
View Code

F. Inversion Expectation

UpSolved.

题意:

有一个排列,有些位置空着,求逆序对的期望

思路:

约定没有确定的数的个数为$x$

对于确定的数,它的贡献由两部分构成

1° 它对其他确定的数的贡献

2° 它对不确定的数的贡献

第一部分 我们可以对确定的数做一遍逆序对,然后乘$fac[x] 即可$

第二部分 我们可以算不确定的数对它的贡献

那么对于不确定的数

1° 它可以在任意的空位上,并且在每个空位上的可能次数为$fac[x - 1]$,

那么在一个空位上的单次贡献是在它前面的比它大的数的个数和在它后面的比它小的个数

这个将不确定的数排序,从小到大做一遍,再从大到小做一遍,我们发现贡献是递增的

每个确定的数只会拿出来做一次

2° 那么对于不确定的数,我们知道,不确定的数可以在任意个空位,

比它大的数如果在它之前的任意空位上就会产生贡献

那么考虑,一个比他大的数在它前面的某个位置,这个时候这两个数的位置确定

剩下的数的排列种树为$fac[x - 2]$

并且比他大的数可以在他前面的任意一个空位

即空位数 * 比它大的数 * fac[x - 2] 就是一个不确定的数产生的贡献

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 200010
  5 #define ll long long
  6 const ll MOD = 998244353;
  7 int n, a[N], b[N], pos[N], sum[N][2]; 
  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 ll fac[N];
 22 void init()
 23 {
 24     fac[0] = 1;
 25     for (int i = 1; i <= 200000; ++i) fac[i] = (fac[i - 1] * i) % MOD;
 26 }
 27 
 28 ll f(ll x) 
 29 {
 30     return x * (x + 1) / 2;
 31 }
 32 
 33 struct BIT
 34 {
 35     int a[N];
 36     void init() { memset(a, 0, sizeof a); }
 37     void update(int x)
 38     {
 39         for (; x <= n; x += x & -x)
 40             ++a[x];
 41     }
 42     int query(int x)
 43     {
 44         int res = 0;
 45         for (; x; x -= x & -x)
 46             res += a[x];
 47         return res;
 48     }
 49 }bit;
 50 
 51 int main()
 52 {
 53     init();
 54     while (scanf("%d", &n) != EOF)
 55     {
 56         memset(pos, -1, sizeof pos);
 57         bit.init();
 58         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
 59         for (int i = 1; i <= n; ++i) if (a[i] != -1)
 60             pos[a[i]] = i;
 61         sum[n + 1][0] = 0;
 62         ll tot[2] = {0, 0};
 63         for (int i = n; i >= 1; --i)
 64             sum[i][0] = sum[i + 1][0] + (a[i] == -1);
 65         for (int i = 1; i <= n; ++i) if (a[i] != -1)
 66             tot[0] += sum[i][0]; 
 67         sum[0][1] = 0;
 68         for (int i = 1; i <= n; ++i) 
 69             sum[i][1] = sum[i - 1][1] + (a[i] == -1);
 70         for (int i = 1; i <= n; ++i) if (a[i] != -1)
 71             tot[1] += sum[i][1];
 72         b[0] = 0;
 73         for (int i = 1; i <= n; ++i) if (pos[i] == -1)
 74             b[++b[0]] = i;
 75         ll res = 0;
 76         int down = 1, up = n;  
 77         for (int i = 1; i <= b[0]; ++i)
 78         {
 79             while (down < b[i]) 
 80             {
 81                 if (pos[down] != -1) tot[0] -= sum[pos[down]][0]; 
 82                 ++down; 
 83             }
 84             res = (res + fac[b[0] - 2] * (f(b[0] - 1) % MOD) % MOD * (b[0] - i) % MOD) % MOD;
 85             res = (res + tot[0] % MOD * fac[b[0] - 1] % MOD) % MOD;
 86         }
 87         for (int i = b[0]; i >= 1; --i)
 88         {
 89             while (up  > b[i])
 90             {
 91                 if (pos[up] != -1) tot[1] -= sum[pos[up]][1];
 92                 --up;
 93             }
 94             res = (res + tot[1] % MOD * fac[b[0] - 1] % MOD) % MOD;
 95         }
 96         ll tmp = 0;
 97         for (int i = 1; i <= n; ++i) if (a[i] != -1)
 98         {
 99             bit.update(a[i]);
100             tmp += bit.query(n) - bit.query(a[i]);
101         }
102         res = (res + tmp * fac[b[0]] % MOD) % MOD;  
103         printf("%lld
", res * qmod(fac[b[0]], MOD - 2) % MOD);
104     }
105     return 0;
106 }
View Code
原文地址:https://www.cnblogs.com/Dup4/p/10193658.html