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\n", l, l * 2); 13 } 14 return 0; 15 }
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 whileView Code(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\n", res % MOD); 29 } 30 return 0; 31 }
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\n", ans[n]); 20 } 21 return 0; 22 }View Code
D. Easy Problem
Unsolevd.
題意:
給處一個字串,有權,求移除一些字元使得花費最少並且沒有一個子序列構成'hard'
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\n", res * qmod(fac[b[0]], MOD - 2) % MOD); 104 } 105 return 0; 106 }View Code