Codeforces Round #664 (Div. 2)
A
题意:
给你四种颜色$r,g,b,w$的球若干,在三个球都不为零的情况下,可以选择$r,g,b$变为$w$,问能否可以把所有的球排列为回文形式。
分析:
可以改变一次会反转奇偶性,再变一次就又回来了,所以只需要考虑变一次的情况。若果不变,那么原本至多一个奇数;如果变,那么原本$3$个或者$4$个奇数可以满足。
第一次交给$WA$了,然后换了个形式写就过了,估计是哪里漏了吧。
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const ll maxn=2e5+100;
5 const ll mod=1e9+7;
6 ll t,n,m,a[maxn];
7 int main(){
8 //freopen("in.txt","r",stdin);
9 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
10 cin>>t;
11 ll r,g,b,w;
12 while(t--){
13 cin>>r>>g>>b>>w;
14 ll ch=r%2+g%2+b%2+w%2;
15 if(ch==1||ch==0){
16 cout<<"YES"<<endl;
17 }else{
18 if(r>0&&g>0&&b>0){
19 if(ch==3||ch==4){
20 cout<<"YES"<<endl;
21 }else cout<<"NO"<<endl;
22 }else cout<<"NO"<<endl;
23 }
24 }
25 return 0;
26 }
B
题意:
在一个$n \times m$的网格钟,给你一个車(象棋的車)处于某一初始位置,要你给出能够抵达所有位置的路线。
分析:
一开始没看清以为只能一步一步走,就说这么麻烦;先把一开始的那一行占掉,然后分在开头还是结尾遍历给出就行。
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const ll maxn=2e5+100;
5 const ll mod=1e9+7;
6 ll t,n,m,x,y,a[maxn];
7 int main(){
8 //freopen("in.txt","r",stdin);
9 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
10 cin>>n>>m>>x>>y;
11 memset(a,0,sizeof(a));
12 cout<<x<<' '<<y<<endl;
13 for(int j=1;j<=m;j++){
14 if(j!=y){
15 cout<<x<<' '<<j<<endl;
16 }
17 }
18 ll ch=1;
19 for(int i=1;i<=n;i++){
20 if(i==x) continue;
21 for(int j=1;j<=m;j++){
22 if(ch==1){
23 cout<<i<<' '<<(m+1-j)<<endl;
24 }else{
25 cout<<i<<' '<<j<<endl;
26 }
27 }
28 if(ch==1) ch=0;
29 else ch=1;
30 }
31 return 0;
32 }
C
题意:
挺多的,就不写了。
分析:
当时看了一下,就没想了。注意到数据量很小(我是没想到原来这么小),暴力枚举$0 \sim 512$的答案。对于某一个答案$x$,由于$x$是从所有的$c_i$或运算得到的,所以$x|c_i=x$,如果对于所有的$a_i$都可以找到一个$b_i$满足条件,那么这个$x$就可以,并且一定是最小的。
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const ll maxn=2e5+100;
5 const ll mod=1e9+7;
6 ll t,n,m,d,a[maxn],b[maxn];
7 int main(){
8 //freopen("in.txt","r",stdin);
9 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
10 cin>>n>>m;
11 for(int i=0;i<n;i++) cin>>a[i];
12 for(int i=0;i<m;i++) cin>>b[i];
13 for(int i=0;i<=(1<<9);i++){
14 ll cnt=0;
15 for(int j=0;j<n;j++){
16 for(int v=0;v<m;v++){
17 if(((a[j]&b[v])|i)==i){
18 cnt++;
19 break;
20 }
21 }
22 }
23 if(cnt==n){
24 cout<<i<<endl;
25 return 0;
26 }
27 }
28 return 0;
29 }
D
题意:
QQ里有个人调戏群主,每次有个调戏值$a_i$,如果$a_i$大于了群主的忍耐度$m$就会被群主禁言$d$天。并且每次如果可以调戏就一定会调戏,问怎么排列可以使得调戏值最大。
分析:
我以为的可以写出来,可能是思路不太好,所以$WA$了挺多还没做出来。预处理的时候,把大于的分到另外一个数组,然后把两个数组颠倒过来,并计算前缀和。策略是先把最大的放到末尾,然后枚举有多少天被禁言。那么对于$i$次禁言,由于调戏后直接减少的天数是$(i-1)(d+1)+1$,剩下的$n-(i-1)(d+1)-1$天贪心的从大到小选取不会被禁言的数组,然后取过程中的最大值就好了。我一开始用的是二分搜索,其实不如枚举来的简单快捷,以后能枚举就枚举。
1 #include<bits/stdc++.h>
2 using namespace std;
3 typedef long long ll;
4 const ll maxn=2e5+100;
5 const ll mod=1e9+7;
6 ll t,n,m,d,a[maxn],b[maxn],sum[maxn];
7 int main(){
8 //freopen("in.txt","r",stdin);
9 ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
10 cin>>n>>d>>m;
11 int num1=1,num2=1;
12 for(int cn=1;cn<=n;cn++){
13 cin>>t;
14 if(t>m) b[num2++]=t;
15 else a[num1++]=t;
16 }
17 if(num2==1){
18 ll res=0;
19 for(int i=1;i<=n;i++){
20 res+=a[i];
21 }cout<<res<<endl;
22 return 0;
23 }
24 sort(a+1,a+num1);reverse(a+1,a+num1);
25 sort(b+1,b+num2);reverse(b+1,b+num2);
26 for(int i=1;i<=n;i++) a[i]+=a[i-1];//小坑这里都要循环到n
27 for(int i=1;i<=n;i++) b[i]+=b[i-1];
28 ll res=-1;
29 for(int i=(num2-1+d)/(d+1);i<num2;i++){
30 if((i-1)*(d+1)+1<=n){
31 res=max(res,b[i]+a[n-(i-1)*(d+1)-1]);
32 }
33 }
34 cout<<res<<endl;
35 //for(int v=1;v<num1;v++) cout<<a[v]<<' ';cout<<endl;
36 return 0;
37 }