Codeforces Round #664 (Div. 2)【ABCD】(題解)
涵蓋知識點:思維、位運算、字首和
比賽連結:傳送門
A - Boboniu Likes to Color Balls
題意: 給定\(r,g,b,w\)四種顏色數量,每次操作可以選擇\(r,g,b\)各一個然後變為三個\(w\),問最後這些顏色能否組成迴文。
題解: 偶數次改變的奇偶性同第一次,所以只要判斷兩種情況。當且僅當奇數的數量為\(0,1\)時才有解。
Accept Code:
#include <bits/stdc++.h> using namespace std; int main(){ int t;cin>>t; while(t--){ int r,g,b,w; cin>>r>>g>>b>>w; int cnt=0; if(r&1)cnt++; if(g&1)cnt++; if(b&1)cnt++; if(w&1)cnt++; if(cnt<=1)puts("Yes"); else{ if(r==0||g==0||b==0)puts("No"); else{ r--,g--,b--,w+=3; int cnt=0; if(r&1)cnt++; if(g&1)cnt++; if(b&1)cnt++; if(w&1)cnt++; if(cnt<=1)puts("Yes"); else puts("No"); } } } return 0; }
B - Boboniu Plays Chess
題意: 給定棋盤大小和一個非邊緣的點,要求給出一種車走的方案遍歷棋盤上的每個點。
題解: 先移到最左邊緣,然後移到\((1,1)\)然後下上下上移動即可。
Accept Code:
#include <bits/stdc++.h> using namespace std; bool vis[110][110]; int main(){ int n,m,x,y; cin>>n>>m>>x>>y; cout<<x<<" "<<y<<"\n"; cout<<x<<" 1\n1 1\n"; vis[x][y]=vis[x][1]=vis[1][1]=true; int flag=1; x=y=1; for(int i=4;i<=m*n+2;i++){ x+=flag; if(!vis[x][y])cout<<x<<" "<<y<<"\n"; if(flag==1&&x==n)flag=-1,y++,x++; if(flag==-1&&x==1)flag=1,y++,x--; } return 0; }
C - Boboniu and Bit Operations
題意: 給定兩個長度分別為\(n,m\)的陣列\(a,b\)。對於每一個\(1\le i\le n\)選擇一個\(1\le j\le m\),令\(c_i=a_i \& b_j\)。求\(c_1|c_2|\ldots |c_{n-1}|c_{n}\)的最小值。
題解: 直接遍歷\(2^9\)之內的所有答案。我們假設答案為\(x\),當且僅當對於所有的\(1\le i\le n\)都能找到一個\(1\le j \le m\)滿足\((a_i\&b_j)|x=x\),這個答案就是合理的。
Accept Code:
#include <bits/stdc++.h> using namespace std; const int maxn=210; int a[maxn],b[maxn]; int main(){ int n,m; cin>>n>>m; for(int i=1;i<=n;i++)cin>>a[i]; for(int i=1;i<=m;i++)cin>>b[i]; for(int x=0;x<=(1<<9);x++){ for(int i=1;i<=n;i++){ bool flag=false; for(int j=1;j<=m;j++){ if(((a[i]&b[j])|x)==x){ flag=true; break; } } if(!flag)goto st; } cout<<x<<"\n"; return 0; st:; } return 0; }
D - Boboniu Chats with Du
題意: Du在群裡發出的值大於\(m\),就會被禁言\(d\)天。給定一個發言序列,要求重新排序,使得在\(n\)天內發出的值總和儘可能大,求最大值。
題解: 將所有的序列按照和\(m\)的大小分成兩類後從大到小貪心排序。我們假設序列中大於\(m\)的值為\(a\),我們用\(x\)遍歷\(0到a\),意思就是我們取大於\(m\)的天數為\(x\)天。那麼算上禁言時間後就會花費\((x-1)(d+1)+1\)天,因為我們可以認為最後一天發言,然後禁言的影響不對最後答案產生負面效果。然後從小於等於\(m\)的貪心選擇剩下的\(n-(x-1)(d+1)-1\)天。遍歷所有可能取最大值即可。
Accept Code:
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
typedef long long ll;
ll a[maxn],b[maxn];
int main(){
int n,d,m,k=0,l=0;
cin>>n>>d>>m;
for(int i=1,x;i<=n;i++){
cin>>x;
if(x>m)a[++k]=x;
else b[++l]=x;
}
if(k==0){
ll ans=0;
for(int i=1;i<=n;i++)ans+=b[i];
cout<<ans<<"\n";
return 0;
}
sort(a+1,a+k+1);
reverse(a+1,a+k+1);
for(int i=1;i<=k;i++)a[i]+=a[i-1];
sort(b+1,b+l+1);
reverse(b+1,b+l+1);
for(int i=1;i<=n;i++)b[i]+=b[i-1];
ll ans=0;
for(int i=(k+d)/(d+1);i<=k;i++){
if(1ll*(i-1)*(d+1)+1<=n)ans=max(ans,a[i]+b[n-1ll*(i-1)*(d+1)-1]);
}
cout<<ans<<"\n";
return 0;
}