zoukankan      html  css  js  c++  java
  • 【Codeforces】CF Round #676 (Div. 2)

    并没有参加。做做里面的题目而已。

    https://codeforces.com

    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
    ",(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),若 ((1,2), (2,1)) 中没有 (0),那么我们把 ((n,n-1), (n-1,n)) 全部变为 (0) 即可;否则我们把 ((1,2), (2,1)) 全部变为 (0)

    第三,(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
    ",(int)(ans.size()));
    		if(ans.size()) rep(i,0,ans.size()-1) printf("%d %d
    ",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
    ",y*c[1]+(x-y)*c[6]);
    		else if(x>0&&y>0&&x<y) printf("%lld
    ",x*c[1]+(y-x)*c[2]);
    		else if(x<0&&y<0&&x>=y) printf("%lld
    ",-x*c[4]+(x-y)*c[5]);
    		else if(x<0&&y<0&&x<y) printf("%lld
    ",-y*c[4]+(y-x)*c[3]);
    		else if(x<=0&&y>=0) printf("%lld
    ",-x*c[3]+y*c[2]);
    		else if(x>=0&&y<=0) printf("%lld
    ",-y*c[5]+x*c[6]);
    	}
    	return 0;
    }
    

    E. Swedish Heroes

    这道题真的神。

    暴力 DP 肯定不行。所以我们观察一下条件。我们可以转化为给每一个数都安排一个正负号,然后统计求和的满足条件的最大值。什么叫做满足条件呢?即存在一种合并的方式,使得得出的结果是这样的一个和。

    然后就是神仙 Observation。我们设正着的数量为 (p),反着的数量为 (q),则可以发现,其中一个充分条件为 (2p+qmod 3 = 1)。充分条件可以归纳证明。

    然后呢?然后有一个很神仙的违背这个条件的例子。+-+-+-.... 等只有加减交错的一个方案。显然这是不可行的。然后,我们发现正反交错是唯一一个违背条件的例子。于是我们大力 DP 即可。

    (f(i,r,0/1,0/1)) 代表前 (i) 个数,(2p+qmod 3=r),第 (i) 个数为负数还是正数,前面是否有非加减交错的存在。

    还有一个坑点,(n=1) 的时候直接输出 (a_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;
    const int N=200009, inf=0x3f3f3f3f3f3f3f3f;
    
    int n,a[N],f[N][3][2][2];
    
    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;
    }
    void upd(int &x,int y) {x=(x>y ? x : y);}
    
    signed main() {
    	n=read();
    	rep(i,1,n) a[i]=read();
    	if(n==1) return printf("%lld
    ",a[1]), 0; 
    	rep(i,1,n) rep(r,0,2) rep(p,0,1) rep(q,0,1) f[i][r][p][q]=-inf;
    	f[1][2][0][0]=-a[1], f[1][1][1][0]=a[1];
    	rep(i,1,n-1) rep(r,0,2) rep(p,0,1) rep(q,0,1)
    		upd(f[i+1][(r+2)%3][0][q||!p],f[i][r][p][q]-a[i+1]),
    		upd(f[i+1][(r+1)%3][1][q|| p],f[i][r][p][q]+a[i+1]);
    	printf("%lld
    ",max(f[n][1][0][1],f[n][1][1][1]));
    	return 0;
    } 
    
  • 相关阅读:
    Azure存储账户的日志分析方法
    导出zabbix监控数据
    centos7下kubernetes(18。kubernetes-健康检查)
    centos7下kubernetes(17。kubernetes-回滚)
    unity接入安卓SDK,与安卓相互通信
    (转)坐标 旋转 计算
    矩阵运算试验
    photonServer学习之连接数据库
    C#委托链
    git命令大全
  • 原文地址:https://www.cnblogs.com/TetrisCandy/p/13875435.html
Copyright © 2011-2022 走看看