码迷,mamicode.com
首页 > 其他好文 > 详细

Codeforces Global Round 1

时间:2019-02-08 10:21:27      阅读:128      评论:0      收藏:0      [点我收藏+]

标签:define   离线   ems   continue   mem   构造   操作   其他   less   

A. Parity

签.

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 int b, k, a[N]; 
 6 
 7 int main()
 8 {
 9     while (scanf("%d%d", &b, &k) != EOF)
10     {
11         int res = 0; 
12         for (int i = 1; i <= k; ++i) scanf("%d", a + i);
13         int base = 1; 
14         for (int i = k; i >= 1; --i)
15         {
16             res = (res + a[i] * base % 2) % 2;
17             base = base * b % 2; 
18         }
19         puts(res % 2 ? "odd" : "even");
20     }
21     return 0;
22 }
View Code

做的时候卡了一会儿

因为想用费马小定理

认为

$b^x = b^{(x \% \phi(m))} \pmod m$

然后幂次都变为$0$

就直接加起来$模2判断一下就好了$

$但是没有考虑到0^0次的问题$

$在这里如果b % 2 == 0, 那么带b的项都为0$

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 int b, k, a[N]; 
 6 
 7 int main()
 8 {
 9     while (scanf("%d%d", &b, &k) != EOF)
10     {
11         int res = 0; 
12         for (int i = 1; i <= k; ++i) scanf("%d", a + i);
13         for (int i = 1; i <= k; ++i)
14             res = (res + a[i] % 2) % 2;
15         if (b % 2 == 0) res = a[k];
16         puts(res % 2 ? "odd" : "even");
17     }
18     return 0;
19 }
View Code

 

 

B. Tape

签.

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 int n, m, k;
 6 int b[N];
 7 
 8 int main()
 9 {
10     while (scanf("%d%d%d", &n, &m, &k) != EOF)
11     {
12         --k;
13         for (int i = 1; i <= n; ++i) scanf("%d", b + i);
14         int res = b[n] - b[1] + 1;
15         priority_queue <int> pq;
16         for (int i = 2; i <= n; ++i) pq.push(b[i] - b[i - 1] - 1);
17         while (!pq.empty() && k--)
18         {
19             res -= pq.top();
20             pq.pop();
21         }
22         printf("%d\n", res);
23     }
24     return 0;
25 }
View Code

 

 

C. Meaningless Operations

Solved.

题意:

给出一个数$a$

$定义(f(a) = max_{1 <= b < a} gcd(a \oplus b, a \& b))$

给出$f(a)$

思路:

考虑$gcd(x, 0) = x$

那么我们构造$(a \& b) = 0, 并且 (a \oplus b)最大即可$

$对于2^x - 1 这种东西是没法构造的$

$考虑这样的数不多,提前打表即可$

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int q, x;
 5 map <int, int> ans;
 6 
 7 int solve(int x)
 8 {
 9     if (ans.find(x) != ans.end()) return ans[x]; 
10     int res;
11     for (int i = 24; i >= 0; --i) if (((x >> i) & 1)) 
12     {
13         res = (1 << (i + 1)) - 1;
14         break;
15     }
16     return ans[x] = res;
17 }
18 
19 int main()
20 {
21 ans[1] = 1,
22 ans[3] = 1,
23 ans[7] = 1,
24 ans[15] = 5,
25 ans[31] = 1,
26 ans[63] = 21,
27 ans[127] = 1,
28 ans[255] = 85,
29 ans[511] = 73,
30 ans[1023] = 341,
31 ans[2047] = 89,
32 ans[4095] = 1365,
33 ans[8191] = 1,
34 ans[16383] = 5461,
35 ans[32767] = 4681,
36 ans[65535] = 21845,
37 ans[131071] = 1,
38 ans[262143] = 87381,
39 ans[524287] = 1,
40 ans[1048575] = 349525,
41 ans[2097151] = 299593,
42 ans[4194303] = 1398101,
43 ans[8388607] = 178481,
44 ans[16777215] = 5592405,
45 ans[33554431] = 1082401;
46     while (scanf("%d", &q) != EOF)
47     {
48         while (q--)
49         {
50             scanf("%d", &x);
51             printf("%d\n", solve(x));
52         }
53     }
54     return 0;
55 }
View Code

 

D. Jongmah

Upsolved.

题意:

有一些数字,三个相同的数字消去

三个连续的也可以消去

求最多消去多少组

思路:

$dp[i][j][k] 表示到第i大的数, 第i - 2大的数还余了j个, 第i - 1个数还余了k个$

$的最大消去的组数$

$转移的时候注意能跟前面的余数组成连续的就组成连续的$

$因为和前面余数组成连续的只需要出一张牌就获得1的贡献$

$如果消去当前三张相同的需要三张牌,至少是不会亏的$

$注意转移的时候要把前面的余数也剪掉$

$再考虑每张牌最多出5张和前面和后面的其他牌组成连续的$

$那么j, k的状态只有6个$

技术图片
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define N 1000010
 6 int n, m, a[N];
 7 ll f[2][6][6];  
 8 
 9 int main()
10 {
11     while (scanf("%d%d", &n, &m) != EOF)
12     {
13         memset(a, 0, sizeof a);
14         memset(f, -1, sizeof f);  
15         for (int i = 1, x; i <= n; ++i) 
16         {
17             scanf("%d", &x);
18             ++a[x];
19         }
20         if (m <= 2) 
21         {
22             printf("%d\n", a[1] / 3 + a[2] / 3);
23             continue; 
24         }
25         ll res = 0;
26         for (int i = 0; i < 6; ++i) 
27             for (int j = 0; j < 6; ++j)
28                 if (a[1] >= i && a[2] >= j)
29                     f[2 & 1][i][j] = (a[1] - i) / 3 + (a[2] - j) / 3; 
30         //for (int i = 1; i <= m; ++i) printf("%d%c", a[i], " \n"[i == m]);    
31         for (int i = 3; i <= m; ++i)
32         {
33             for (int j = 0; j < 6; ++j)
34                 for (int k = 0; k < 6; ++k)
35                     f[i & 1][j][k] = -1;
36             for (int j = 0; j < 6; ++j)
37             {
38                 for (int k = 0; k < 6; ++k) if (f[(i & 1) ^ 1][j][k] != -1)
39                 {
40                     for (int o = 0; o < 6; ++o) 
41                     {
42                         int need = min(j, min(a[i] - o, k));
43                         ll base = f[(i & 1) ^ 1][j][k];
44                         if (a[i] >= o) 
45                         {
46                             for (int w = 0; w <= need; ++w) 
47                                 f[i & 1][k - w][o] = max(f[i & 1][k - w][o], base + (a[i] - o - w) / 3 + w);     
48                         }
49                     }
50                 }
51             }
52             //for (int j = 0; j < 3; ++j)
53             //    for (int k = 0; k < 3; ++k)
54             //        printf("%d %d %d %lld\n", i, j, k, f[i][j][k]);
55         }
56         for (int i = 0; i < 6; ++i) 
57             for (int j = 0; j < 6; ++j)
58                 res = max(res, f[m & 1][i][j]);
59         printf("%lld\n", res);
60     }    
61     return 0;
62 }
View Code

 

E. Magic Stones

Upsolved.

题意:

有一个数字序列$A[], 每次可以选择一个i \in [2, n - 1]$

$使得 A[i] = A[i + 1] + A[i - 1] - A[i]$

问能否经过一些这样的操作,使得$A[] -> B[]$

思路:

我们令$d[i] = A[i + 1] - A[i]$

我们考虑$上述的那个操作$

$d_i = A[i + 1] - (A[i + 1] + A[i - 1] - A[i]) = A[i] - A[i - 1] = d_{i - 1}$

同理

$d_{i - 1} = d_{i}$

我们注意到,这个操作变成了交换元素

$那么把B[]数组也变成差分数组,如果两个差分数组通过任意交换后相同$

$那么原序列通过以系列操作也可以相同$

$即排个序判断是否相同即可,再注意一下第一个是否相同$

 

 

F. Nearest Leaf

Upsolved.

题意:

给出一个树, 询问$离v节点最近叶子节点的距离$

注意给出的点序是$DFS序$

思路:

将询问离线,令根为$1$

$考虑如果询问1号点,那么跑一遍DFS,将所有点的距离丢进线段树$

$查最小值即可$

那么对于一个点$x$

我们考虑从线段树里面维护的距离是到它父亲$y的距离$

$那么我们要把这个距离转变成到x的距离$

$可以发现,它子树内的点都需要减去一条边,就是它父亲到它那条边$

$它子树外的点都需要加上一条边,是它父亲到它那条边$

$子树内的点是连续的,所以可以在线段树上操作$

 

Codeforces Global Round 1

标签:define   离线   ems   continue   mem   构造   操作   其他   less   

原文地址:https://www.cnblogs.com/Dup4/p/10355916.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!