Codeforces Round 941 (Div. 2) Div 1 cf941 A-D

 

A

感觉A比较复杂啊,相比较B简单明了。

way1

只要有相同的一个数,它的数目大于等于k,那么它就可以进行一次操作,接下来可以再摸k-1个数,那么对于无法凑成k个数的数字来说,无论现在它有多少个数(>=1),加上这k-1个数,都能凑成数目>=k。同时,这个操作可以无限循环下去。

所以这道题的出题设计还是比较精妙的。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 map<int,int> m;
15 
16 int main()
17 {
18     int T,n,k,d,i,x,y,z,result;
19     scanf("%d",&T);
20     while (T--)
21     {
22         x=y=z=0;
23         result=0;
24         m.clear();
25 
26         scanf("%d%d",&n,&k);
27         for (i=0;i<n;i++)
28         {
29             scanf("%d",&d);
30             m[d]++;
31         }
32 
33         for (auto par:m)
34         {
35             x += par.second / k * (k-1);
36             //y += (k-1) - (k - par.second%k);
37             y += max(par.second%k - 1, 0);
38             z += par.second;
39         }
40 
41         if (x==0)
42             result=z;
43         else
44         {
45             result = x+y;
46             while (result>=k)
47                 result = result%k + result/k*(k-1);
48         }
49 
50         //printf("Case %d : ",T);
51         printf("%d\n",result);
52     }
53 
54     return 0;
55 }

 

way2

A 数目大于等于k的数,记录可以执行变化的操作数目,对应可以摸的数目

B 数目小于k的数,从大到小排序,依次利用A摸到的数,增加这个数的数目,看能否数目到达k个,然后可以归类为A

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 map<int,int> m;
15 vector<int> vec(1005);
16 
17 int main()
18 {
19     int T,n,k,d,i,rest,result;
20     scanf("%d",&T);
21     while (T--)
22     {
23         rest=0;
24         result=0;
25         m.clear();
26         vec.clear();
27 
28         scanf("%d%d",&n,&k);
29         for (i=0;i<n;i++)
30         {
31             scanf("%d",&d);
32             m[d]++;
33         }
34 
35         for (auto par:m)
36         {
37             rest += (par.second / k) * (k-1);
38             vec.push_back( par.second % k );
39         }
40 
41         sort(vec.begin(), vec.end());
42         reverse(vec.begin(), vec.end());
43         //result += accumulate(vec.begin(), vec.end(), 0);
44 
45         for (auto v:vec)
46             if (rest >= k - v)
47             {
48                 rest += k-1 - (k-v);
49             }
50             else
51                 result+=v;
52 
53         while (rest>=k)
54             rest = rest%k + rest/k*(k-1);
55         result+=rest;
56 
57         //printf("Case %d : ",T);
58         printf("%d\n",result);
59     }
60 
61     return 0;
62 }

 

B

对于某个颜色,

行的最小=1,最大=n

列的最小=1,最大=m

只要满足这个条件就行,无论黑色还是白色

好的代码写法能很快写完

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 int main()
15 {
16     int T,n,m,i,j,u1,u2,u3,u4,v1,v2,v3,v4;
17     char c;
18     //xmin,xmax,ymin,ymax
19     scanf("%d",&T);
20     while (T--)
21     {
22         u1=u2=u3=u4=v1=v2=v3=v4=0;
23         scanf("%d%d",&n,&m);
24         for (i=1;i<=n;i++)
25         {
26             scanf("%c",&c);
27             for (j=1;j<=m;j++)
28             {
29                 scanf("%c",&c);
30                 if (c=='W')
31                 {
32                     if (i==1)
33                         u1=1;
34                     if (i==n)
35                         u2=1;
36                     if (j==1)
37                         u3=1;
38                     if (j==m)
39                         u4=1;
40                 }
41                 else
42                 {
43                     if (i==1)
44                         v1=1;
45                     if (i==n)
46                         v2=1;
47                     if (j==1)
48                         v3=1;
49                     if (j==m)
50                         v4=1;
51                 }
52             }
53         }
54         //printf("Case %d : ",T);
55         if ((u1+u2+u3+u4==4) || (v1+v2+v3+v4==4))
56             printf("YES\n");
57         else
58             printf("NO\n");
59     }
60 
61     return 0;
62 }

 

C

cf的test case和最后才大数据评测比较搞人心态,也算是一种磨练了,多年没打,没意识到,打div1,没想到栽在了这上面。

好像没怎么看到人hack?感觉好hack?

这种题,类型多,按道理是挺容易出错的。如果是atcoder,就认真造样例检查了……虽然cf更加是如此……

div1的ac/wrong submisson率,高得有点吓人。

我觉得D比C,好写难说,但基本上D不容易出错。

 

 

回想,首先,保证0 wrong submisson,因为1wa,10mins罚时,而且不容易找到错误。在此基础上,怎么用时比较短。怎么让做这道题时,思路比较清晰?

我感觉我容易栽在这类题上,因为思路不清楚,很容易绕、晕……

 

 

去掉重复的数字,然后从小到大排序

如果第一个数大于1,无论怎么样,Alice总能使得当前最小的数是1,保证最后Alice能赢 

如果一开始是1、2、3、……这样的序列,

a. 如果序列是1、2、3、……、k,如果k是奇数,Alice赢;否则Bob赢。因为每次都只能取一个数。

b. 如果序列是1、2、3、……、k,m(m>k+1),…… 如果k是奇数,Bob赢;否则Alice赢。因为一开始每次都只能取一个数,直到变成m-k(m-k>1),……这样的序列。如果k是奇数,对于m-k当前这个情况,是Bob开始拿,因为m-k>1,所以最后是Bob赢。同理k是偶数,Alice赢。

 

注意,去掉重复的数字后,数目不是n,不要下标写错了。真的是心态爆炸……

 

写成这样方便复制?:{printf("Alice\n"); continue;}

 

  1 #include <cstdio>
  2 #include <cstdlib>
  3 #include <cstring>
  4 #include <cmath>
  5 #include <cstdbool>
  6 #include <string>
  7 #include <algorithm>
  8 #include <iostream>
  9 #include <sstream>
 10 #include <ctime>
 11 #include <stack>
 12 #include <vector>
 13 #include <queue>
 14 #include <set>
 15 #include <map>
 16 #include <array>
 17 #include <bitset>
 18 using namespace std;
 19 #define LL long long
 20 #define ULL unsigned long long
 21 
 22 const LL mod_1=1e9+7;
 23 const LL mod_2=998244353;
 24 
 25 const double eps_1=1e-5;
 26 const double eps_2=1e-10;
 27 
 28 const int maxn=2e5+10;
 29 
 30 set<int> s;
 31 
 32 int a[maxn];
 33 
 34 int main()
 35 {
 36     int T,q,n,d,i,cond;
 37     scanf("%d",&T);
 38     while (T--)
 39     {
 40         s.clear();
 41         cond=0;
 42         n=0;
 43 
 44         scanf("%d",&q);
 45         while (q--)
 46         {
 47             scanf("%d",&d);
 48             if (s.find(d)==s.end())
 49             {
 50                 a[n++]=d;
 51                 s.insert(d);
 52             }
 53         }
 54         sort(a,a+n);
 55 
 56         a[n]=a[n-1]+1;
 57         for (i=0;i<n;i++)
 58             if (a[i]!=a[i+1]-1)
 59                 break;
 60         if (i!=n)
 61             cond=i & 1;
 62         else
 63             cond=n & 1;
 64 
 65         if (a[0]!=1)
 66             {printf("Alice\n"); continue;}
 67 
 68         if (cond==1)
 69             printf("Alice\n");
 70         else
 71             printf("Bob\n");
 72     }
 73 
 74     return 0;
 75 }
 76 /*
 77 100
 78 2
 79 1 7
 80 4
 81 1 2 3 7
 82 5
 83 1 2 3 4 7
 84 5
 85 1 2 3 7 8
 86 
 87 
 88 2
 89 1 2
 90 4
 91 1 2 3 4
 92 5
 93 1 2 3 4 5
 94 6
 95 1 1 1 1 1 1
 96 6
 97 1 2 1 2 2 1
 98 
 99 
100 
101 100
102 
103 2
104 2 2
105 
106 4
107 2 2 2 3
108 
109 4
110 1 2 4 5
111 
112 5
113 1 2 4 5 6
114 
115 4
116 1 2 3 7
117 
118 5
119 1 2 3 7 8
120 */

 

 

暴力打表验证

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 #define LL long long
  4 #define ULL unsigned long long
  5 
  6 const LL mod_1=1e9+7;
  7 const LL mod_2=998244353;
  8 
  9 const double eps_1=1e-5;
 10 const double eps_2=1e-10;
 11 
 12 const int maxn=2e5+10;
 13 int print_1=0;
 14 
 15 int dfs(vector<int> vec)
 16 {
 17     if (vec.size()==1)
 18         return 1;
 19 
 20     vector<int>::iterator it, next_it;
 21     int value=vec[0], i, cur=0;
 22     for (i=1;i<=value;i++)
 23     {
 24         for (it=vec.begin(); it!=vec.end(); it++)
 25             *it = (*it)-1;
 26 
 27         if (i==value)
 28         {
 29             /*
 30             for (it=vec.begin();it!=vec.end();it++)
 31             {
 32                 if ((*it)==0)
 33                     vec.erase(it);
 34             }
 35             */
 36 
 37             ///如果所有都是0,会删除错误
 38             if (vec.back()==0)
 39                 return 1;
 40 
 41             for (it=vec.begin();it!=vec.end();it=next_it)
 42             {
 43                 next_it=it+1;
 44                 if ((*it)==0)
 45                     vec.erase(it);
 46             }
 47 
 48             /*
 49             if (vec.empty())
 50                 return 1;
 51             */
 52         }
 53 
 54         if (print_1)
 55         {
 56             printf("array: ");
 57             for (auto d:vec)
 58                 printf("%d ",d);
 59             printf("\n");
 60             printf("\n");
 61         }
 62 
 63         cur |= (dfs(vec)^1);
 64     }
 65     return cur;
 66 }
 67 
 68 int main()
 69 {
 70     vector<int> v;
 71     int mode=1,a,n,i;
 72     if (mode==1)
 73     {
 74         while (1)
 75         {
 76             v.clear();
 77 
 78             scanf("%d",&n);
 79             for (i=1;i<=n;i++)
 80             {
 81                 scanf("%d",&a);
 82                 v.push_back(a);
 83             }
 84             sort(v.begin(), v.end());
 85 
 86             //printf("%d\n", dfs(v));   ///1 Alice ; 0 Bob
 87             printf("%s\n", dfs(v)==1 ? "Alice" : "Bob" );
 88 
 89         }
 90 
 91 
 92     }
 93 
 94     return 0;
 95 }
 96 /*
 97 
 98 
 99 3
100 1 2 3
101 
102 4
103 1 2 3 4
104 
105 5
106 1 2 3 4 5
107 
108 6
109 1 2 3 4 5 6
110 
111 3
112 2 3 4
113 
114 4
115 2 3 4 5
116 
117 5
118 2 3 4 5 6
119 
120 6
121 2 3 4 5 6 7
122 
123 
124 
125 
126 result:
127 3
128 1 2 3
129 Alice
130 
131 4
132 1 2 3 4
133 Bob
134 
135 5
136 1 2 3 4 5
137 Alice
138 
139 6
140 1 2 3 4 5 6
141 Bob
142 
143 3
144 2 3 4
145 Alice
146 
147 4
148 2 3 4 5
149 Alice
150 
151 5
152 2 3 4 5 6
153 Alice
154 
155 6
156 2 3 4 5 6 7
157 Alice
158 
159 
160 
161 
162 一段
163 
164 
165 从1开始   双数: Bob;单数:Alice
166 从2开始   都是Alice
167 
168 
169 
170 ======
171 
172 
173 6
174 1 2 3 4 6 7
175 
176 7
177 1 2 3 4 6 7 8
178 
179 8
180 1 2 3 4 6 7 8 9
181 
182 
183 5
184 1 2 3 6 7
185 
186 6
187 1 2 3 6 7 8
188 
189 7
190 1 2 3 6 7 8 9
191 
192 
193 
194 
195 result:
196 6
197 1 2 3 4 6 7
198 Alice
199 
200 7
201 1 2 3 4 6 7 8
202 Alice
203 
204 8
205 1 2 3 4 6 7 8 9
206 Alice
207 5
208 1 2 3 6 7
209 Bob
210 
211 6
212 1 2 3 6 7 8
213 Bob
214 
215 7
216 1 2 3 6 7 8 9
217 Bob
218 
219 
220 ======
221 
222 
223 
224 
225 8
226 1 2 3 4 6 7 9 10
227 
228 9
229 1 2 3 4 6 7 9 10 11
230 
231 10
232 1 2 3 4 6 7 9 10 11 12
233 
234 
235 
236 6
237 1 2 3 6 7 10
238 
239 7
240 1 2 3 6 7 10 11
241 
242 8
243 1 2 3 6 7 10 11 12
244 
245 
246 
247 
248 
249 
250 result:
251 
252 8
253 1 2 3 4 6 7 9 10
254 Alice
255 
256 9
257 1 2 3 4 6 7 9 10 11
258 Alice
259 
260 10
261 1 2 3 4 6 7 9 10 11 12
262 Alice
263 
264 
265 
266 6
267 1 2 3 6 7 10
268 Bob
269 
270 7
271 1 2 3 6 7 10 11
272 Bob
273 
274 8
275 1 2 3 6 7 10 11 12
276 Bob
277 
278 
279 
280 
281 
282 ======
283 
284 8
285 1 2 3 6 7 8 9 11
286 
287 9
288 1 2 3 6 7 8 9 11 12
289 
290 10
291 1 2 3 6 7 8 9 11 12 13
292 
293 
294 8
295 1 2 3 6 7 8 9 11
296 Bob
297 
298 9
299 1 2 3 6 7 8 9 11 12
300 Bob
301 
302 10
303 1 2 3 6 7 8 9 11 12 13
304 Bob
305 
306 
307 
308 
309 ======
310 
311 
312 7
313 1 2 4 5 6 8 9
314 
315 
316 
317 
318 //三段
319 
320 A
321 
322 ======
323 
324 7
325 2 3 5 6 7 9 10
326 //三段
327 
328 A
329 
330 ======
331 
332 4
333 1 2 4 5
334 A
335 
336 4
337 1 2 4 5 6
338 A
339 
340 //二段
341 
342 
343 ======
344 
345 10
346 1 2 3 10 12 13 20 21 22 30
347 B
348 
349 11
350 1 2 3 10 12 13 20 21 22 30 31
351 B
352 
353 12
354 1 2 3 10 12 13 20 21 22 30 31 32
355 B
356 
357 
358 ======
359 
360 
361 
362 11
363 1 2 3 10 12 13 20 21 22 25 30
364 B
365 
366 12
367 1 2 3 10 12 13 20 21 22 25 30 31
368 B
369 
370 
371 13
372 1 2 3 10 12 13 20 21 22 25 30 31 32
373 B
374 
375 ======
376 
377 10
378 2 3 4 11 13 14 21 22 23 31
379 A
380 
381 11
382 2 3 4 11 13 14 21 22 23 31 32
383 A
384 
385 12
386 2 3 4 11 13 14 21 22 23 31 32 33
387 A
388 
389 
390 8
391 2 3 4 5 6 10 11 12
392 A
393 
394 
395 8
396 
397 
398 
399 ======
400 
401 
402 
403 
404 */

 

 

 

 

 

 

 

D

n的要求才1e6,所以可以大开大合的构造:

对于不能为k

a. 1、2、4、... 相加,直到小于等于(k-1)。 这些数的和为A。

b. (k-1)-A。 使得a、b这两类数的和为(k-1),同时,可以任意数相加和可以为1~(k-1)。

c. k+1、k+2、k+3 三个数。a、b、c这三类数,可以任意数相加和可以为1~(2*k-1)。 这个就是大致构造,大致感觉可以就行。

d. k*2、k*4、k*8、... 剩余凑齐25个数。

 

设计理念:

a 1~k-1要有:若干个,1、2、...,直到不能满足任意数相加和为k

b 不能有2i,否则加上a里的数,任意数相加可以为k

c 要有k+1 否则无法使得任意数相加和为k+1

d 经过处理后,1~r除去k,任意数相加都可以变为它们

e 在d的基础上,2r,4r,8r,…… 凑够25个数

 

 

不要对于比较小的k,都制定一组数,这样工作量大,很累,很容易出错,浪费大量时间。n<=1e6太小了,完全有很多选择,浪费多一两个数,也能构造出成功、设计很简单的例子。

通过k=1~15,看结果,判断是否可以。assert(最后一个数>=5e5)

 

 

看了题解,这个数字上的描述,就很简洁明了:

 

1~ 2i-1 包含 1~ 2i-1 

再加上k-2包含 1~ k-1

再加上k+1 包含 1~k+1 除去k

k+1+2i 包含 1~k+1+2i 除去k。这一步是为了使得满足1~2i+1-1

然后就是再加上 2i+1,2i+2,……

 

设计理念:

当满足1~x后,加上2i(2i<=x),满足1~x+2i

当满足1~x+2i后,加上2i+1(2i+1<=x+2i),满足1~x+2i+1

依次类推

就是1~x,加上2i,2i+1……2j 满足x+2j

对于0,加上20,20+1……2j 满足2j+1

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long
 4 #define ULL unsigned long long
 5 
 6 const LL mod_1=1e9+7;
 7 const LL mod_2=998244353;
 8 
 9 const double eps_1=1e-5;
10 const double eps_2=1e-10;
11 
12 const int maxn=2e5+10;
13 
14 int er[100],result[100];
15 
16 int main()
17 {
18     int T,n,k,m,i,j,maxs=25;
19     er[0]=1;
20     for (i=1;er[i-1]<=1e7;i++)
21         er[i]=er[i-1]<<1;
22     scanf("%d",&T);
23     while (T--)
24     {
25         scanf("%d%d",&n,&k);
26         m=k-1;
27         i=0;
28         j=0;
29         while (m>=er[i])
30         {
31             result[j++]=er[i];
32             m-=er[i];
33             i++;
34         }
35         if (m>0)
36             result[j++]=m;
37         result[j++]=k+1;
38         result[j++]=k+2;
39         result[j++]=k+3;
40 
41         result[j++]=k*2;
42         while (j<maxs)
43         {
44             result[j]=result[j-1]*2;
45             j++;
46         }
47 
48         //assert(result[maxs-1]>1e6);
49 
50         printf("%d\n",maxs);
51 
52         for (i=0;i<maxs;i++)
53         {
54             printf("%d",result[i]);
55             if (i==maxs-1)
56                 printf("\n");
57             else
58                 printf(" ");
59         }
60     }
61 
62     return 0;
63 }
64 /*
65 15
66 1 1
67 1 2
68 1 3
69 1 4
70 1 5
71 1 6
72 1 7
73 1 8
74 1 9
75 1 10
76 1 11
77 1 12
78 1 13
79 1 14
80 1 15
81 */

 

posted @ 2024-05-06 21:45  congmingyige  阅读(12)  评论(0编辑  收藏  举报