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 }

代码君

时间: 2024-10-19 02:05:21

CodeForces Round #320 Div2的相关文章

Codeforces Round#320 Div2 解题报告

Codeforces Round#320 Div2 先做个标题党,骗骗访问量,结束后再来写咯. codeforces 579A Raising Bacteria codeforces 579B Finding Team Member codeforces 579C A Problem about Polyline codeforces 579D "Or" Game codeforces 579E Weakness and Poorness codeforces 579F LCS Aga

codeforces round #257 div2 C、D

本来应该认真做这场的,思路都是正确的. C题,是先该横切完或竖切完,无法满足刀数要求,再考虑横切+竖切(竖切+横切), 因为横切+竖切(或竖切+横切)会对切割的东西产生交叉份数,从而最小的部分不会尽可能的大. 代码如下,虽然比较长.比较乱,但完全可以压缩到几行,因为几乎是4小块重复的代码,自己也懒得压缩 注意一点,比如要判断最小块的时候,比如9行要分成2份,最小的剩下那份不是9取模2,而应该是4 m/(k+1)<=m-m/(k+1)*k          #include<bits/stdc+

codeforces Round #250 (div2)

a题,就不说了吧 b题,直接从大到小排序1-limit的所有数的lowbit,再从大到小贪心组成sum就行了 1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #define N 200000 6 using namespace std; 7 int pos[N],a[N],s[N],f[N],la[N],b[N],i,j,k,ans,n,p

Codeforces Round #254(div2)A

很有趣的题.想到了就非常简单,想不到就麻烦了. 其实就是一种逆向思维:最后结果肯定是这样子: WBWBWBWB... BWBWBWBW... WBWBWBWB... ... 里面有“-”的地方改成“-”就行了. 但是我开始是正着想的,想每个点怎么处理,这还要看它周围点的状态,越想越麻烦... 这题中体现的正难则反的逆向思维很值得学习. #include<iostream> #include<cstdio> #include<cstdlib> #include<cs

Codeforces Round #254(div2)B

就是看无向图有几个连通块,答案就是2n-num. 范围很小,就用矩阵来存图减少代码量. #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set> #include<vector> #include<algorithm> #inc

Codeforces Round #260(div2)C(递推)

有明显的递推关系: f[i]表示i为数列中最大值时所求结果.num[i]表示数i在数列中出现了几次. 对于数i,要么删i,要么删i-1,只有这两种情况,且子问题还是一样的思路.那么很显然递推一下就行了:f[i]=max(f[i-1],f[i-2]+i*num[i]); 这里技巧在于:为了防止麻烦,干脆就所有数的出现次数都记录一下,然后直接从2推到100000(类似于下标排序),就不用排序了,也不用模拟删除操作了.这一技巧貌似简单,但实际上临场想出来也需要点水平. #include<iostrea

Codeforces Round #289 Div2 E

Problem 给一串长度为N的字符串,对于每个字符,若字符为元音,则权值为1,否则为0.一个子串的权值定义为该串所有字符权值之和除以字符个数,一个母串的权值定义为所有子串的权值之和.求母串的权值. Limits Time Limit(ms): 1000 Memory Limit(MB): 256 N: [1, 5*10^5] 字符集: 'A'-'Z' 元音: I E A O U Y Solution 考虑每个元音字符对母串的贡献,可以找出规律. More 举"ABCDOEFGHKMN"

Codeforces Round #403 div2 C. Andryusha and Colored Balloons

题目链接:Codeforces Round #403 div2 C. Andryusha and Colored Balloons 题意: 给你一棵n个节点的树,然后让你染色,规定相连的三个 节点不能同色,问需要的最少颜色,并输出其中一种方案. 题解: 因为只有相邻3个节点不同色. 所以直接DFS,每个节点都从1开始. 然后ans[v]!=ans[u]!=ans[fa]就行. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i&

CodeForces Round#229 DIV2 C 递推DP

对这道题目也只好说呵呵了,没注意k的范围最大才10,所以昨晚纠结了很久,没什么好的方法来处理,后来无奈想去翻翻题解,发现人家开头就来了句,因为k的范围比较小 所以.........我只好暂停马上回头看看题目,是的,k比较小所以完全可以先在询问前预处理DP一遍, DP就比较清晰了,dp[i][j]  (i>=0 && i<k,,,,j>=i && j <=n)代表意义呢 以i为开头的  区间[1,j]注意 是 1~j的 所需要的操作数,题目问的是最小操