Codeforces Global Round 1

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 
 5 #define ll long long
 6 #define N 1000010
 7 int n, m, a[N];
 8 ll f[2][6][6];  
 9 
10 int main()
11 {
12     while (scanf("%d%d", &n, &m) != EOF)
13     {
14         memset(a, 0, sizeof a);
15         memset(f, -1, sizeof f);  
16         for (int i = 1, x; i <= n; ++i) 
17         {
18             scanf("%d", &x);
19             ++a[x];
20         }
21         if (m <= 2) 
22         {
23             printf("%d\n", a[1] / 3 + a[2] / 3);
24             continue; 
25         }
26         ll res = 0;
27         for (int i = 0; i < 6; ++i) 
28             for (int j = 0; j < 6; ++j)
29                 if (a[1] >= i && a[2] >= j)
30                     f[2 & 1][i][j] = (a[1] - i) / 3 + (a[2] - j) / 3; 
31         //for (int i = 1; i <= m; ++i) printf("%d%c", a[i], " \n"[i == m]);    
32         for (int i = 3; i <= m; ++i)
33         {
34             for (int j = 0; j < 6; ++j)
35                 for (int k = 0; k < 6; ++k)
36                     f[i & 1][j][k] = -1;
37             for (int j = 0; j < 6; ++j)
38             {
39                 for (int k = 0; k < 6; ++k) if (f[(i & 1) ^ 1][j][k] != -1)
40                 {
41                     for (int o = 0; o < 6; ++o) 
42                     {
43                         int need = min(j, min(a[i] - o, k));
44                         ll base = f[(i & 1) ^ 1][j][k];
45                         if (a[i] >= o) 
46                             f[i & 1][k - need][o] = max(f[i & 1][k - need][o], base + (a[i] - o - need) / 3 + need);     
47                     }
48                 }
49             }
50             //for (int j = 0; j < 3; ++j)
51             //    for (int k = 0; k < 3; ++k)
52             //        printf("%d %d %d %lld\n", i, j, k, f[i][j][k]);
53         }
54         for (int i = 0; i < 6; ++i) 
55             for (int j = 0; j < 6; ++j)
56                 res = max(res, f[m & 1][i][j]);
57         printf("%lld\n", res);
58     }    
59     return 0;
60 }
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[]数组也变成差分数组,如果两个差分数组通过任意交换后相同$

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

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

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 int n, c[N], t[N];
 6 int a[N], b[N];
 7 
 8 bool ok()
 9 {
10     for (int i = 1; i < n; ++i)
11         if (a[i] != b[i])
12             return false;
13     return true;
14 }
15 
16 int main()
17 {
18     while (scanf("%d", &n) != EOF)
19     {
20         for (int i = 1; i <= n; ++i)
21         {
22             scanf("%d", c + i);
23             if (i > 1)
24                 a[i - 1] = c[i] - c[i - 1];
25         }
26         for (int i = 1; i <= n; ++i)
27         {
28             scanf("%d", t + i);
29             if (i > 1)
30                 b[i - 1] = t[i] - t[i - 1];
31         }
32         sort(a + 1, a + n);
33         sort(b + 1, b + n);
34         puts(ok() && c[1] == t[1] ? "Yes" : "No");
35     }
36     return 0;
37 }
View Code

 

 

F. Nearest Leaf

Upsolved.

题意:

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

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

思路:

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

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

$查最小值即可$

那么对于一个点$x$

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

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

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

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

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

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define ll long long
  5 #define N 500010
  6 int n, q;
  7 struct qnode
  8 {
  9     int l, r, id;
 10     qnode () {}
 11     qnode (int l, int r, int id) : l(l), r(r), id(id) {}
 12 };
 13 vector <qnode> vec[N];
 14 ll ans[N];
 15 struct Graph
 16 {
 17     struct node
 18     {
 19         int to, nx, w;
 20         node () {}
 21         node (int to, int nx, int w) : to(to), nx(nx), w(w) {}
 22     }a[N << 1];
 23     int head[N], pos;
 24     void init()
 25     {
 26         memset(head, 0, sizeof head);
 27         pos = 0;
 28     }    
 29     void add(int u, int v, int w)
 30     {
 31         a[++pos] = node(v, head[u], w); head[u] = pos;
 32         a[++pos] = node(u, head[v], w); head[v] = pos;
 33     }
 34 }G;
 35 #define erp(u) for (int it = G.head[u], v = G.a[it].to, w = G.a[it].w; it; it = G.a[it].nx, v = G.a[it].to, w = G.a[it].w)
 36 int fa[N], isleaf[N]; ll dis[N]; 
 37 
 38 namespace SEG
 39 {
 40     ll Min[N << 2], lazy[N << 2];
 41     void pushup(int id) { Min[id] = min(Min[id << 1], Min[id << 1 | 1]); }
 42     void build(int id, int l, int r)
 43     {
 44         lazy[id] = 0;
 45         if (l == r)
 46         {
 47             Min[id] = dis[l]; 
 48             if (!isleaf[l]) Min[id] = (ll)1e18; 
 49             return;
 50         }
 51         int mid = (l + r) >> 1;
 52         build(id << 1, l, mid);
 53         build(id << 1 | 1, mid + 1, r);
 54         pushup(id);
 55     }
 56     void pushdown(int id)
 57     {
 58         if (!lazy[id]) return;
 59         lazy[id << 1] += lazy[id];
 60         lazy[id << 1 | 1] += lazy[id];
 61         Min[id << 1] += lazy[id];
 62         Min[id << 1 | 1] += lazy[id];
 63         lazy[id] = 0;
 64     }
 65     void update(int id, int l, int r, int ql, int qr, ll val)
 66     {
 67         if (l >= ql && r <= qr)
 68         {
 69             Min[id] += val;
 70             lazy[id] += val;
 71             return;
 72         }
 73         pushdown(id);
 74         int mid = (l + r) >> 1;
 75         if (ql <= mid) update(id << 1, l, mid, ql, qr, val);
 76         if (qr > mid) update(id << 1 | 1, mid + 1, r, ql, qr, val);
 77         pushup(id);
 78     }
 79     ll query(int id, int l, int r, int ql, int qr)
 80     {
 81         if (l >= ql && r <= qr) return Min[id];
 82         pushdown(id);
 83         int mid = (l + r) >> 1;
 84         ll res = (ll)1e18;
 85         if (ql <= mid) res = min(res, query(id << 1, l, mid, ql, qr));
 86         if (qr > mid) res = min(res, query(id << 1 | 1, mid + 1, r, ql, qr));
 87         return res;
 88     }
 89 }
 90 
 91 int lp[N], rp[N];
 92 void DFS1(int u)
 93 {
 94     lp[u] = u;
 95     rp[u] = u;
 96     erp(u) if (v != fa[u])
 97     {
 98         fa[v] = u;
 99         dis[v] = dis[u] + w;
100         DFS1(v);
101         rp[u] = max(rp[u], rp[v]);
102     }
103     isleaf[u] = (lp[u] == rp[u]);
104 }
105 
106 void DFS2(int u)
107 {
108     for (auto it : vec[u])
109         ans[it.id] = SEG::query(1, 1, n, it.l, it.r);
110     erp(u) if (v != fa[u])
111     {
112         SEG::update(1, 1, n, 1, n, w);
113         SEG::update(1, 1, n, lp[v], rp[v], -2ll * w);
114         DFS2(v);
115         SEG::update(1, 1, n, 1, n, -w);
116         SEG::update(1, 1, n, lp[v], rp[v], 2ll * w);
117     }
118 }
119     
120 int main()
121 {
122     while (scanf("%d%d", &n, &q) != EOF)
123     {
124         for (int i = 1; i <= n; ++i) vec[i].clear();
125         G.init();
126         for (int i = 2, p, w; i <= n; ++i)
127         {
128             scanf("%d%d", &p, &w);
129             G.add(i, p, w);
130         }
131         for (int i = 1, v, l, r; i <= q; ++i)
132         {
133             scanf("%d%d%d", &v, &l, &r);
134             vec[v].emplace_back(l, r, i);
135         }
136         dis[1] = 0;
137         DFS1(1);
138         SEG::build(1, 1, n);
139         DFS2(1);
140         for (int i = 1; i <= q; ++i) printf("%lld\n", ans[i]);
141     }    
142     return 0;
143 }
View Code

 

posted @ 2019-02-08 10:06  Dup4  阅读(349)  评论(0编辑  收藏  举报