【Codeforces】CF Round #676 (Div. 2)
阿新 • • 發佈:2020-10-26
並沒有參加。做做裡面的題目而已。
A. XORwice
每次給定 \(a,b\),求出 $(a \(\operatorname{xor}\) x)+(b \(\operatorname{xor}\) x)$ 的最小值。
將其拆位。假設是兩個一,那麼我們考慮這一位 \(xor 1\)。對於其他情況,我們是不需要 \(xor 1\) 的,因為這不會使答案更差。
#include<bits/stdc++.h> #define int long long #define rep(i,a,b) for(register int i=(a);i<=(b);i++) using namespace std; bool bit(int s,int i) {return (1ll<<i)&s;} inline int read() { register int x=0, f=1; register char c=getchar(); while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();} while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();} return x*f; } signed main() { int T=read(); rep(t,1,T) { int a=read(), b=read(), x=0; rep(i,0,30) { if(bit(a,i)&&bit(b,i)) x+=(1ll<<i); } printf("%lld\n",(a^x)+(b^x)); } return 0; }
B. Putting Bricks in the Wall
給定一個網格圖,有點權 \(0,1\)。請你反轉最多 \(2\) 個點的點權,使得沒有任何一條從 \((1,1)\) 到 \((n,n)\) 的路徑上的點權全部相同。
\(f(x,y,0/1)\) 代表若終點為 \((x,y)\),是否有路徑點權為 \(0/1\) 的路徑。現在分幾種情況。
第一,\(f(n,n,0)=f(n,n,1)=1\),我們讓 \((n,n-1), (n-1,n)\) 變為 \(0\), (1,2), (2,1)$ 全部變為 \(1\) 即可。(可以證明這樣子只會用兩次反轉機會)。
第二,\(f(n,n,0)=0, f(n,n,1)=1\)
第三,\(f(n,n,0)=1, f(n,n,1)=0\),和上面反一下即可。
第四,\(f(n,n,0)=f(n,n,1)=0\),直接輸出 \(0\)。
#include<bits/stdc++.h> #define rep(i,a,b) for(register int i=(a);i<=(b);i++) using namespace std; const int N=209; int T,n,cnt[2][2]; char c[N][N]; bool f[N][N][2]; vector<pair<int,int> >ans; void chp(int x,int y,int val) { if(c[x][y]!=val+'0') ans.push_back(make_pair(x,y)); } int main() { scanf("%d",&T); while(T--) { scanf("%d",&n); rep(i,1,n) scanf("%s",c[i]+1); f[1][1][0]=f[1][1][1]=1; rep(i,1,n) rep(j,1,n) if(i!=1||j!=1) { f[i][j][1]=(f[i-1][j][1]&&c[i-1][j]!='0')||(f[i][j-1][1]&&c[i][j-1]!='0'); f[i][j][0]=(f[i-1][j][0]&&c[i-1][j]!='1')||(f[i][j-1][0]&&c[i][j-1]!='1'); } memset(cnt,0,sizeof(cnt)); cnt[0][c[1][2]-'0']++, cnt[0][c[2][1]-'0']++, cnt[1][c[n][n-1]-'0']++, cnt[1][c[n-1][n]-'0']++; ans.clear(); if(f[n][n][0]&&f[n][n][1]||cnt[0][0]==1&&cnt[0][1]==1&&cnt[1][0]==1) chp(n,n-1,0), chp(n-1,n,0), chp(1,2,1), chp(2,1,1); else if(f[n][n][1]&&!f[n][n][0]) { if(c[1][2]!='0'&&c[2][1]!='0') chp(n,n-1,0), chp(n-1,n,0); else chp(1,2,0), chp(2,1,0); } else if(f[n][n][0]&&!f[n][n][1]) { if(c[1][2]!='1'&&c[2][1]!='1') chp(n,n-1,1), chp(n-1,n,1); else chp(1,2,1), chp(2,1,1); } printf("%d\n",(int)(ans.size())); if(ans.size()) rep(i,0,ans.size()-1) printf("%d %d\n",ans[i].first,ans[i].second); } return 0; }
C. Palindromifier
生草結論構造題。
可以證明,輸出
R n-1
L n
L 2
即可。
D. Hexagons
其實這道題並不難。首先發現我們可以通過對每一個 \(c_i\) 都鬆弛一下的方法,之後就可以直接貪心。於是我們直接先鬆弛 \(c_i=\min(c_i,c_{i-1}+c_{i+1})\)。然後我們可以直接貪心取邊。儘可能地選擇 \(c_4\) 和 \(c_1\) 即可。注意分類討論。
#include<bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
using namespace std;
inline int read() {
register int x=0, f=1; register char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1; c=getchar();}
while(c>='0'&&c<='9') {x=(x<<3)+(x<<1)+c-48,c=getchar();}
return x*f;
}
int t,x,y,c[9];
signed main() {
t=read();
while(t--) {
x=read(), y=read();
rep(i,1,6) c[i]=read();
rep(i,1,6) c[i]=min(c[i],c[i==1 ? 6 : i-1]+c[i==6 ? 1 : i+1]);
if(x>0&&y>0&&x>=y) printf("%lld\n",y*c[1]+(x-y)*c[6]);
else if(x>0&&y>0&&x<y) printf("%lld\n",x*c[1]+(y-x)*c[2]);
else if(x<0&&y<0&&x>=y) printf("%lld\n",-x*c[4]+(x-y)*c[5]);
else if(x<0&&y<0&&x<y) printf("%lld\n",-y*c[4]+(y-x)*c[3]);
else if(x<=0&&y>=0) printf("%lld\n",-x*c[3]+y*c[2]);
else if(x>=0&&y<=0) printf("%lld\n",-y*c[5]+x*c[6]);
}
return 0;
}