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;
}