CodeForces Round #320 Div2
A. Raising Bacteria
计算一下x的bitcount就是答案。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 int bitcount(int x) 8 { 9 int ans = 0; 10 while(x) 11 { 12 if(x & 1) ans++; 13 x >>= 1; 14 } 15 return ans; 16 } 17 18 int main() 19 { 20 int x; scanf("%d", &x); 21 printf("%d\n", bitcount(x)); 22 23 24 return 0; 25 }
B. Finding Team Member
贪心
从大到小排个序,如果两个人都没有舞伴那就结为一组。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 using namespace std; 5 6 const int maxn = 800 + 10; 7 8 struct FK 9 { 10 int r, c, d; 11 FK() {} 12 FK(int r, int c, int d):r(r), c(c), d(d) {} 13 14 bool operator < (const FK& a) const 15 { 16 return d > a.d; 17 } 18 }fk[maxn * maxn]; 19 20 int n; 21 22 int match[maxn]; 23 24 int main() 25 { 26 int tot = 0; 27 scanf("%d", &n); n <<= 1; 28 29 for(int i = 2; i <= n; i++) 30 for(int j = 1; j < i; j++) 31 { 32 int x; scanf("%d", &x); 33 fk[tot++] = FK(i, j, x); 34 } 35 36 sort(fk, fk + tot); 37 38 int remain = n; 39 for(int i = 0; i < tot && remain; i++) 40 { 41 FK& e = fk[i]; 42 int u = e.r, v = e.c; 43 if(!match[u] && !match[v]) 44 { 45 match[u] = v; 46 match[v] = u; 47 remain -= 2; 48 } 49 } 50 51 for(int i = 1; i < n; i++) printf("%d ", match[i]); 52 printf("%d\n", match[n]); 53 54 return 0;
C. A Problem about Polyline
题意:
给出 (0, 0) – (x, x) – (2x, 0) – (3x, x) – (4x, 0) – ... - (2kx, 0) – (2kx + x, x) – .... 这样一条折线,和上面一点(a, b)。求可能的最小的x
分析:
首先(a, b)与原点连线的斜率最大是1,绝对不会超过1. 所以一开始判断一下,如果b > a,无解。
分情况讨论(a, b)是上升点还是下降点:
- (a, b)是上升点,那么点(a - b, 0)一定在折线上,所以得到 a - b = 2kx (k是正整数)。x = (a - b) / (2k),注意到折线上的点纵坐标最大值为x,所以x应该满足x≥b。所以有k ≤ (a - b) / (2b),k取最大值时,x取得最小值。
- (a, b)是下降点,和前一种情况一样。点(a + b, 0)一定在折线上,后面的分析思路和上面一样。
这两种情况算出来两个x的最小值再取最小值就是答案。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 int main() 10 { 11 LL a, b; cin >> a >> b; 12 13 if(b > a) { puts("-1"); return 0; } 14 if(a == b) { printf("%I64d.000000000000\n", a); return 0; } 15 16 double x1, x2; 17 LL k = (a - b) / (b * 2); 18 x1 = 1.0 * (a - b) / 2.0 / k; 19 k = (a + b) / (b * 2); 20 x2 = 1.0 * (a + b) / 2.0 / k; 21 x1 = min(x1, x2); 22 23 printf("%.12f\n", x1); 24 25 return 0; 26 }
D. "Or" Game
这个题是贪心,但是有种黑科技的赶脚,目前没想明白贪心的理由。
贪心的方法是:既然操作不超过k次,那么k次操作直接用在同一个数上面。然后枚举k次操作在哪个数上面,预处理一下前缀后缀的或运算的值,时间复杂度为O(n)。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 using namespace std; 6 7 typedef long long LL; 8 9 const int maxn = 200000 + 10; 10 11 LL a[maxn], pre[maxn], suf[maxn]; 12 13 int main() 14 { 15 int n, k; 16 LL x; 17 scanf("%d%d%I64d", &n, &k, &x); 18 19 for(int i = 1; i <= n; i++) 20 { 21 scanf("%I64d", a + i); 22 pre[i] = pre[i - 1] | a[i]; 23 } 24 for(int i = n; i > 0; i--) suf[i] = suf[i + 1] | a[i]; 25 26 LL x0 = x; 27 for(int i = 2; i <= k; i++) x *= x0; 28 29 LL ans = 0; 30 for(int i = 1; i <= n; i++) ans = max(ans, pre[i-1] | (a[i] * x) | suf[i+1]); 31 32 printf("%I64d\n", ans); 33 34 return 0; 35 }
E. Weakness and Poorness
很明显,当x向两边趋于正负很大的数的时候,序列{ ai - x }的weakness也是变大的。
但不明显的一点就是,为什么中间只有一个极值?
如果中间只有一个极值的话,就可以用三分找到对应的极小值,同时也是最小值。
关于weakness的计算:
我们可以用线性时间的DP来计算数列的最大连续子序列:
d(i)表示以ai结尾的子序列的最大值,状态转移为d(i) = max{ d(i-1) + ai, ai }
同样地,再计算一个最小连续子序列,取两者绝对值的最大值就是整个序列的weakness
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <cmath> 6 using namespace std; 7 8 const int maxn = 200000 + 10; 9 const double eps = 1e-9; 10 11 int n; 12 double a[maxn]; 13 14 double Calc(double x) 15 { 16 double ans = 0, p = 0, q = 0; 17 for(int i = 1; i <= n; i++) 18 { 19 double t = a[i] - x; 20 if(p > 0) p += t; else p = t; 21 if(q < 0) q += t; else q = t; 22 ans = max(ans, max(p, -q)); 23 } 24 25 return ans; 26 } 27 28 int main() 29 { 30 //freopen("in.txt", "r", stdin); 31 32 scanf("%d", &n); 33 for(int i = 1; i <= n; i++) scanf("%lf", a + i); 34 35 //printf("%.7f\n%.7f\n", Calc(2), Calc(1.75)); 36 37 double L = -1e5, R = 1e5, ans; 38 for(;;) 39 { 40 double t = (R - L) / 3.0; 41 double Lmid = L + t, Rmid = R - t; 42 double ansL = Calc(Lmid), ansR = Calc(Rmid); 43 44 if(fabs(ansL - ansR) < eps) { ans = ansL; break; } 45 46 if(ansL > ansR) L = Lmid; 47 else R = Rmid; 48 } 49 50 printf("%.7f\n", ans); 51 52 return 0; 53 }