Codeforces Round #554 (div. 2)

距离上次打cf已经不知道过了多久,看到最近的contest都很水,于是想上上分,然后就3题滚了……(顺便吐槽cf好卡

题目链接:http://codeforces.com/contest/1152


A:

一眼题,奇+偶才能等于奇

 1 #include <bits/stdc++.h>
 2 /* define */
 3 #define ll long long
 4 #define dou double
 5 #define pb emplace_back
 6 #define mp make_pair
 7 #define fir first
 8 #define sec second
 9 #define sot(a,b) sort(a+1,a+1+b)
10 #define rep1(i,a,b) for(int i=a;i<=b;++i)
11 #define rep0(i,a,b) for(int i=a;i<b;++i)
12 #define repa(i,a) for(auto &i:a)
13 #define eps 1e-8
14 #define int_inf 0x3f3f3f3f
15 #define ll_inf 0x7f7f7f7f7f7f7f7f
16 #define lson curPos<<1
17 #define rson (curPos<<1)+1
18 /* namespace */
19 using namespace std;
20 /* header end */
21 
22 const int maxn=1e5;
23 int n,m,ja=0,oa=0,jb=0,ob=0;
24 
25 int main()
26 {
27     scanf("%d%d",&n,&m);
28     rep1(i,1,n) {
29         int x; scanf("%d",&x);
30         if (x&1) ja++; else oa++;
31     }
32     rep1(i,1,m) {
33         int x; scanf("%d",&x);
34         if (x&1) jb++; else ob++;
35     }
36     int ans=0;
37     ans=min(ja,ob); ans+=min(oa,jb);
38     printf("%d
",ans);
39     return 0;
40 }
View Code

B:

给定整数x,轮流执行两种操作:1)x=x xor 2^n-1,2)x++。问要经过几次操作才能把x变为2^n-1的形式。看到这个题第一反应居然是……不会,发了好久的呆才缓过来。

对于当前的x,转化为二进制,并找到最高位的0。比如10011,最高位0到最右边长度为4,那就用1111去xor x。

事实上写起来也不用这么麻烦,一直用跟x等长的"1"串去xor x,直到(++x)-lowbit(x)==0就可以了。

在?为什么没有一眼秒?

 1 /* basic header */
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <cstring>
 7 #include <cmath>
 8 #include <cstdint>
 9 #include <climits>
10 #include <float.h>
11 /* STL */
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <queue>
16 #include <stack>
17 #include <algorithm>
18 #include <array>
19 #include <iterator>
20 /* define */
21 #define ll long long
22 #define dou double
23 #define pb emplace_back
24 #define mp make_pair
25 #define fir first
26 #define sec second
27 #define init(a,b) fill(begin(a),end(a),b)
28 #define sot(a,b) sort(a+1,a+1+b)
29 #define rep1(i,a,b) for(int i=a;i<=b;++i)
30 #define rep0(i,a,b) for(int i=a;i<b;++i)
31 #define repa(i,a) for(auto &i:a)
32 #define eps 1e-8
33 #define int_inf 0x3f3f3f3f
34 #define ll_inf 0x7f7f7f7f7f7f7f7f
35 #define lson curPos<<1
36 #define rson curPos<<1|1
37 /* namespace */
38 using namespace std;
39 /* header end */
40 
41 vector<int>ans;
42 int n, op = 0;
43 
44 inline int lowbit(int x)
45 {
46     return x & -x;
47 }
48 
49 int get(int x)
50 {
51     int ret = 1;
52     while (ret <= x) ret <<= 1;
53     return ret - 1;
54 }
55 
56 int calc(int x)
57 {
58     int ret = 0, tmp = 1;
59     while (tmp <= x) ret++, tmp <<= 1;
60     return ret;
61 }
62 
63 int check(int x)
64 {
65     x++;
66     if (x - lowbit(x)) return true; else return false;
67 }
68 
69 int main()
70 {
71     scanf("%d", &n);
72     while (check(n))
73     {
74         op++;
75         if (op & 1)
76         {
77             ans.pb(calc(n));
78             n ^= get(n);
79         }
80         else n++;
81     }
82     printf("%d
", op);
83     for (auto i : ans) printf("%d ", i);
84     puts("");
85     return 0;
86 }
View Code

C:

给定整数a,b,求一非负数k,使得lcm(a+k,b+k)最小。

gcd(a+k,b+k)==gcd(a+k,abs(a-b)),它还有个名字叫更相减损术(想起来了吧)。令delta=abs(a-b),枚举delta的所有因子并反推k。

为什么要这样做?题目让lcm最小,那么就是要求最大的gcd,最大的gcd必定是两数中最大的约数,由于题目中delta是定值,所以就可以枚举delta的约数,然后把a凑到含有此约数为止,需要凑的值k=x-a%x (x | delta)。

 1 /* basic header */
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <cstring>
 7 #include <cmath>
 8 #include <cstdint>
 9 #include <climits>
10 #include <float.h>
11 /* STL */
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <queue>
16 #include <stack>
17 #include <algorithm>
18 #include <array>
19 #include <iterator>
20 /* define */
21 #define ll long long
22 #define dou double
23 #define pb emplace_back
24 #define mp make_pair
25 #define fir first
26 #define sec second
27 #define init(a,b) fill(begin(a),end(a),b)
28 #define sot(a,b) sort(a+1,a+1+b)
29 #define rep1(i,a,b) for(int i=a;i<=b;++i)
30 #define rep0(i,a,b) for(int i=a;i<b;++i)
31 #define repa(i,a) for(auto &i:a)
32 #define eps 1e-8
33 #define int_inf 0x3f3f3f3f
34 #define ll_inf 0x7f7f7f7f7f7f7f7f
35 #define lson curPos<<1
36 #define rson curPos<<1|1
37 /* namespace */
38 using namespace std;
39 /* header end */
40 
41 ll a, b, minLcm = 0, ans = 0, delta;
42 
43 ll lcm(ll a, ll b)
44 {
45     return a / __gcd(a, b) * b;
46 }
47 
48 int main()
49 {
50     scanf("%lld%lld", &a, &b); delta = abs(b - a);
51     minLcm = lcm(a, b);
52     for (ll i = 1; i * i <= delta; i++)
53     {
54         if (!(delta % i))
55         {
56             ll tmp = i - (a % i);
57             if (lcm(a + tmp, b + tmp) < minLcm)
58             {
59                 minLcm = lcm(a + tmp, b + tmp);
60                 ans = tmp;
61             }
62             tmp = (delta / i) - (a % (delta / i));
63             if (lcm(a + tmp, b + tmp) < minLcm)
64             {
65                 minLcm = lcm(a + tmp, b + tmp);
66                 ans = tmp;
67             }
68         }
69     }
70     printf("%lld
", ans);
71     return 0;
72 }
View Code

D:

比赛打到这里,整个人开始自闭起来。读完题就意识到trie只是个幌子,正解是dp,但完全不会做,赛后看大佬代码才懂。

n<=1000已经强烈暗示这很可能是O(n^2)的算法了。

 1 /* basic header */
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <cstring>
 7 #include <cmath>
 8 #include <cstdint>
 9 #include <climits>
10 #include <float.h>
11 /* STL */
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <queue>
16 #include <stack>
17 #include <algorithm>
18 #include <array>
19 #include <iterator>
20 /* define */
21 #define ll long long
22 #define dou double
23 #define pb emplace_back
24 #define mp make_pair
25 #define fir first
26 #define sec second
27 #define init(a,b) fill(begin(a),end(a),b)
28 #define sot(a,b) sort(a+1,a+1+b)
29 #define rep1(i,a,b) for(int i=a;i<=b;++i)
30 #define rep0(i,a,b) for(int i=a;i<b;++i)
31 #define repa(i,a) for(auto &i:a)
32 #define eps 1e-8
33 #define int_inf 0x3f3f3f3f
34 #define ll_inf 0x7f7f7f7f7f7f7f7f
35 #define lson curPos<<1
36 #define rson curPos<<1|1
37 /* namespace */
38 using namespace std;
39 /* header end */
40 
41 const int maxn = 1e3 + 10;
42 const int mod = 1e9 + 7;
43 
44 int n, dp[maxn][maxn][2];
45 
46 int main()
47 {
48     scanf("%d", &n);
49     rep1(i, 0, n)
50     {
51         dp[i][i + 1][0] = -int_inf;
52         dp[n + 1][i][0] = -int_inf;
53     }
54     dp[n][n][0] = dp[n][n][1] = 0;
55     for (int i = n; i >= 0; i--)
56     {
57         for (int j = i - (j == n); j >= 0; j--)
58         {
59             dp[i][j][0] = (dp[i][j + 1][1] + dp[i + 1][j][1]) % mod;
60             dp[i][j][1] = (dp[i][j + 1][0] + dp[i + 1][j][1] + 1) % mod;
61             dp[i][j][1] = (dp[i][j][0] + ((i + j) & 1)) % mod;
62         }
63     }
64     printf("%d
", dp[0][0][1]);
65     return 0;
66 }
View Code

E:

看完题就意识到这肯定是搜索相关,图论题。题意那么绕,其实只是输出欧拉路而已。(居然是模板题,出题人莫不是宫崎英高?(本来可以四题的,被D卡到自闭不想动,摔

 1 /* basic header */
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <cstdlib>
 5 #include <string>
 6 #include <cstring>
 7 #include <cmath>
 8 #include <cstdint>
 9 #include <climits>
10 #include <float.h>
11 /* STL */
12 #include <vector>
13 #include <set>
14 #include <map>
15 #include <queue>
16 #include <stack>
17 #include <algorithm>
18 #include <array>
19 #include <iterator>
20 /* define */
21 #define ll long long
22 #define dou double
23 #define pb emplace_back
24 #define mp make_pair
25 #define fir first
26 #define sec second
27 #define init(a,b) fill(begin(a),end(a),b)
28 #define sot(a,b) sort(a+1,a+1+b)
29 #define rep1(i,a,b) for(int i=a;i<=b;++i)
30 #define rep0(i,a,b) for(int i=a;i<b;++i)
31 #define repa(i,a) for(auto &i:a)
32 #define eps 1e-8
33 #define int_inf 0x3f3f3f3f
34 #define ll_inf 0x7f7f7f7f7f7f7f7f
35 #define lson curPos<<1
36 #define rson curPos<<1|1
37 /* namespace */
38 using namespace std;
39 /* header end */
40 
41 const int maxn = 1e5 + 10;
42 int n, a[maxn], b[maxn];
43 map<int, multiset<int>>graph;
44 vector<int>eulerPath, oddPoint;
45 
46 void getEulerPath(int u)
47 {
48     while (graph[u].size())
49     {
50         int v = *graph[u].begin();
51         graph[u].erase(graph[u].begin());
52         graph[v].erase(graph[v].find(u));
53         getEulerPath(v);
54     }
55     eulerPath.pb(u);
56 }
57 
58 bool checkEuler()
59 {
60     for (auto i : graph)
61     {
62         if ((int)i.second.size() & 1) oddPoint.pb(i.first);
63     }
64     return ((!(int)oddPoint.size()) || ((int)oddPoint.size() == 2));
65 }
66 
67 int main()
68 {
69     scanf("%d", &n);
70     rep0(i, 1, n) scanf("%d", &a[i]);
71     rep0(i, 1, n) scanf("%d", &b[i]);
72     rep0(i, 1, n)
73     {
74         if (a[i] > b[i]) return puts("-1"), 0;
75         graph[a[i]].insert(b[i]);
76         graph[b[i]].insert(a[i]);
77     }
78     if (!checkEuler()) return puts("-1"), 0;
79     getEulerPath(oddPoint.empty() ? graph.begin()->first : oddPoint[0]);
80     if ((int)eulerPath.size() != n) return puts("-1"), 0;
81     for (auto i : eulerPath) printf("%d ", i);
82     puts("");
83     return 0;
84 }
View Code

F1 && F2:

看完题就觉得zen zen不可做,溜了溜了。这数据量我很怀疑是不是状压dp。(被官方题解爆智商了。

原文地址:https://www.cnblogs.com/JHSeng/p/10768886.html