标签:force 字符串 can rem 预处理 最小 pen mem names
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 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\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 }
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 }
Educational Codeforces Round 57 Solution
标签:force 字符串 can rem 预处理 最小 pen mem names
原文地址:https://www.cnblogs.com/Dup4/p/10193658.html