Codeforces Round #676 (Div. 2)

A

输出x x o r xor xor y就可以了,刚开始拿个两个二进制看了一下代码还手打了个xor。。

#include <bits/stdc++.h>
using namespace std;
 
int main(){
	int T;
	scanf("%d",&T);
	int x,y;
	int ans,temp;
	while(T--){
		scanf("%d%d",&x,&y);
		ans=0;
		temp=1;
		while(x!=0||y!=0){
			if((x%2)!=(y%2))
				ans+=temp;
			x/=2;
			y/=2;
			temp<<=1;
		}
		printf("%d\n",ans);
	}
} 

B - Putting Bricks in the Wall

让起点和终点旁边两个格子不同就可以了

#include <bits/stdc++.h>
using namespace std;
int T;
int n;
char g[210][210];
int main(){

	cin>>T;
	while(T--){
		cin>>n;
		for(int i=0;i<n;i++){
			scanf("%s",g[i]);
		}
		char a,b,c,d;
		a=g[0][1];
		b=g[1][0];
		c=g[n-2][n-1];
		d=g[n-1][n-2];
		if(a==b){
			if(c==d){
				if(a!=c){
					cout<<0<<endl;
				}
				else{
					cout<<2<<endl;
					cout<<1<<" "<<2<<endl;
					cout<<2<<" "<<1<<endl;
				}
			}
			else{
				cout<<1<<endl;
				if(c==a){
					cout<<n-1<<" "<<n<<endl;
				}
				else{
					cout<<n<<" "<<n-1<<endl;
				}
			}
		}
		else{
			if(c==d){
				cout<<1<<endl;
				if(a==c){
					cout<<1<<" "<<2<<endl;
				}
				else{
					cout<<2<<" "<<1<<endl;
				}
			}
			else{
				cout<<2<<endl;
				cout<<1<<" "<<2<<endl;
				if(c!=a){
					cout<<n-1<<" "<<n<<endl;
				}
				else{
					cout<<n<<" "<<n-1<<endl;
				}
			}
		}
		
	}
	
}

C - Palindromifier

reversed很关键,刚开始没看见对着样例迷惑了半天,看到后感觉是有肯定可以构造出来的方法。所以尝试是用普通的串进行下模拟。
先看一个最普通的串 a b c d e f abcdef abcdef
我们可以通过翻转很容易的得到 a b c d e f e d c b abcdefedcb abcdefedcb
但是a由于是第一位所以我们不能把它放到后面
所以我们应该先把a放到串的中间,先去构造 b a b c d e f babcdef babcdef
再得到 b a b c d e f e d c b a babcdefedcba babcdefedcba
这个时候我们就可以把b填到末尾

#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
int main(){
	string s;
	cin>>s;
	int l=s.length();
	cout<<3<<endl;
	cout<<"L"<<" "<<2<<endl;
	cout<<"R"<<" "<<2<<endl;
	cout<<"R"<<" "<<l+1+(l+1-2)-1<<endl;
} 

D. Hexagons

只要求出通往各个方向实际的最小代价就好了,刚开始以为要用最短路模板,后来发现六边形外面边的权值会和终点到外面几个点相同,只要分析下就可以得到六个方向的最小代价,最后分成六个区域找最短就可以了。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=1e5+10;
int T;
ll w[10];
int x,y;
int main(){
	cin>>T;
	ll ans;
	while(T--){
		cin>>x>>y;	
		for(int i=0;i<6;i++){
			cin>>w[i];
		}
		for(int i=0;i<6;i++){
			w[i]=min(w[(i+6-1)%6]+w[(i+1)%6],w[i]);
		}
		if(x>=0&&y>=0){
			if(x>=y){
				ans=y*w[0]+(x-y)*w[5];
			}
			else{
				ans=x*w[0]+(y-x)*w[1];
			}
		}
		else if(x<=0&&y<=0){
			x=abs(x);
			y=abs(y);
			if(x>=y){
				ans=y*w[3]+(x-y)*w[2];
			} 
			else{
				ans=x*w[3]+(y-x)*w[4];
			}
		}
		else if(x<=0&&y>=0){
			ans=abs(x)*w[2]+y*w[1];
		}
		else{
			ans=x*w[5]+abs(y)*w[4];
		}
		
		cout<<ans<<endl;
	}
	
} 

E. Swedish Heroes

读题可以知道,每个位置的数对于最后答案的贡献是-1或者1,所以需要观察取1和-1的规律。
对于a,b,c,d四个数有
(((a,b),c),d) -1 -1 1 -1
((a,b),(c,d)) 1 1 1 1
((a,(b,c)),d) 1 -1 -1 -1
(a,((b,c),d))-1 -1 -1 1
(a,(b,(c,d)))-1 1 -1 -1
五种情况,我之后又罗列了五个数的情况,发现-1数量的在不同情况之间都是相差3的倍数。所以我们只要能找出一种情况,我们便知道了所有-1值的可能性。
又发现4个数字可以取成一个,可以一直重复这个操作到数字的数量为4个以内,得出一种可能性。
还有个坑点就是一定有两个相邻的数字最后的贡献是相同的。
接下来就是dp了。

写完了以后看见规律可以总结为-1数量x和n的和是三的倍数
别人严谨的证明加简单的规律。。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxn=2e5+10;
const ll inf=1e16+10;
ll num[maxn];
ll dp[maxn][3][2];
int n;
int main(){
	cin>>n;
	memset(dp,-inf,sizeof(dp));
	for(int i=0;i<n;i++){
		cin>>num[i];
	}
	if(n==1){
		cout<<num[0]<<endl;
		return 0;
	}
	int x=n;
	int r;
	while(x>=4){
		x=x/4+x%4;
	}
	if(x==1)
		r=0;
	else if(x==2)
		r=n%3;
	else if(x==3)
		r=1;
		
	dp[0][0][1]=num[0];
	dp[0][1][0]=-num[0];
	for(int i=1;i<n;i++)
    {
        for(int j=0;j<3;j++)
        {
            if((i+1)&1)
            {
                dp[i][j][1]=dp[i-1][j][1]+num[i];
                dp[i][j][0]=dp[i-1][(j+2)%3][1]-num[i];
            }
            else
            {
                dp[i][j][1]=dp[i-1][(j+2)%3][1]-num[i];
                dp[i][j][0]=dp[i-1][j][1]+num[i];
            }
            dp[i][j][0]=max(dp[i][j][0],dp[i-1][j][0]+num[i]);
            dp[i][j][0]=max(dp[i][j][0],dp[i-1][(j+2)%3][0]-num[i]);
        }
    }
    cout<<dp[n-1][r][0]<<endl;
	
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值