2526 最大异或和
- 2.0 秒
- 262,144.0 KB
- 20 分
- 3级题
给定nn个数x1…xnx1…xn,请你选择n个数p1…pnp1…pn,使得p1<=x1,p2<=x2......p1<=x1,p2<=x2......,并且p1xorp2…pnp1xorp2…pn的值尽量大。问这个最大的异或和是多少。
n≤100,0≤xi≤109n≤100,0≤xi≤109
收起
输入
第一行一个正整数 n 。 第二行 n 个非负整数表示 x[1...n] 。
输出
一行一个数表示答案。
输入样例
3 2 2 2
输出样例
3
分析:
这个题和下面那个题都是二进制拆分+运算性质。
这一题,我们把所有的二进制都拆开,因为我们可以选在比他小的任意一个数,假如一个数的二进制为1000,则他的最后三位是可以任意构造的,即1000 1001 1010 1011……那我们异或最大肯定是每一位都不相同才是最大的。所以我们用num[i]保存i的dii为1的个数,如果遇到了第一个1,则后面的都可以为1。
比如:
1001000
0100
100
ans=1001111
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
LL a[N],power[100];
int num[N];
int n;
void cal(LL x)
{
int j=0;
while(x)
{
if(x%2==1)
num[j]++;
x/=2;
j++;
}
}
int main()
{
scanf("%d",&n);
LL ans=0;
for(int i=1; i<=n; i++)
{
scanf("%lld",&a[i]);
cal(a[i]);
}
for(int i=35; i>=0; i--)
{
if(num[i]==1)
{
ans+=pow(2,i);
}
else if(num[i]>=2)
{
for(int j=i; j>=0; j--)
ans+=pow(2,j);
break;
}
}
printf("%lld\n",ans);
return 0;
}
2527 Or 和 Sum
- 2.0 秒
- 262,144.0 KB
- 20 分
- 3级题
给定两个非负整数 pairOr,pairSumpairOr,pairSum,请你构造两个非负整数 A,BA,B,使得A|B=pairOr,A+B=pairSumA|B=pairOr,A+B=pairSum。
你只需输出是否能构造出满足条件的 A,BA,B 。若可以,输出 PossiblePossible ,否则输出
ImpossibleImpossible 。
0<=pairOr,pairSum<=10180<=pairOr,pairSum<=1018
收起
输入
一行两个数,分别表示pairOr和pairSum。
输出
一行一个字符串。若可以,输出 Possible ,否则输出 Impossible 。
输入样例
7 11
输出样例
Possible
这题考察了一个进位的东西。
a+b=sum与a|b=or把他们看成二进制位相加,还是很好做的,我们知道|,只有在对应二进制位都为0的时候才能为1,即如果or的二进制位为0,则sum的二进制为0,但有一种特殊的情况,就是进位,比如
1011
1011
or: 1011
sum:10110
所以需要保证or0的前一个位置为1即可。
还有就是sum的二进制位个数要么等于or的二进制位个数,要么等于or的二进制位个数+1
题解:
规律代码
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
LL n,m;
int num[10][100];
int maxx;
void cal(int i,LL x)
{
int j=0;
while(x)
{
if(x%2==1)
num[i][j]=1;
x/=2;
j++;
}
num[i][99]=j;
maxx=max(j,maxx);
}
int main()
{
scanf("%lld%lld",&n,&m);
if(n>m)
{
printf("Impossible\n");
return 0;
}
maxx=-1e9;
cal(1,n);
cal(2,m);
/*
for(int i=32; i>=0; i--)
{
cout<<num[1][i];
}
cout<<endl;
for(int i=32; i>=0; i--)
{
cout<<num[2][i];
}
cout<<endl;
cout<<num[1][99]<<" "<<num[2][99]<<endl; */
if(num[1][99]>num[2][99]||(num[1][99]<num[2][99]&&num[1][99]!=num[2][99]-1))
{
printf("Impossible\n");
return 0;
}
for(int i=maxx; i>=0; i--)
{
if(num[1][i]==0&&num[2][i]==1)
{
if(i>0&&num[1][i-1]!=1)
{
//cout<<i<<endl;
printf("Impossible\n");
return 0;
}
}
}
printf("Possible\n");
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
int main()
{
ll x,y;
cin>>x>>y;
ll c=y-x;
if((c|x)==x)
cout<<"Possible"<<endl;
else
cout<<"Impossible"<<endl;
return 0;
}