CodeForces Round #320 Div2

A. Raising Bacteria

计算一下x的bitcount就是答案。

 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

贪心

从大到小排个序,如果两个人都没有舞伴那就结为一组。

 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的最小值再取最小值就是答案。

 

 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)。

 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

 

 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 }
代码君

 

转载于:https://www.cnblogs.com/AOQNRMGYXLMV/p/4816633.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值