考试题玄学解法
以下是题目
“与”
(and.pas/.c/.cpp)
【题目描述】
数学大神HYY又开始发威了,他随口给出一道题:有一个长度为n的序列A,请你求出一对Ai,Aj(1<=i<j<=n)使Ai“与”Aj的值最大。
Ps:“与”表示位运算and,在c++中表示为&。
【输入描述】
第一行为n。接下来n行,一行一个整数表示Ai。
【输出描述】
输出最大的Ai“与”Aj的结果。
【样例输入】
3
8
10
2
【样例输出】
8
【样例解释】
8 and 10 = 8
8 and 2 = 0
10 and 2 = 2
【数据范围】
20%的数据保证n<=5000
100%的数据保证 n<=3*105,0<=Ai<=109
玄学贪心跑过正解,一直被人卡,从未被卡掉
要AC只需要贪心前三个高位1即可
同学的毒瘤数据逼着我贪到了第9个.......
#include<cstdio>
#include<cstring>
#define N 300005
#define inf 0x7f7f7f7f
//ÐþѧËã·¨µÈÄãÀ´¿¨
using namespace std;
inline int read(){
int e=0,ch=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')ch=-1;c=getchar();}
while(c>='0'&&c<='9'){e=e*10+(c-48);c=getchar();}
return e*ch;
}
int n,cnt,minn=inf,minn2=inf,minn3=inf,minn4=inf,minn5=inf,minn6=inf,minn7=inf,minn8=inf,minn9=inf,ans;
int a[N],c[N],d[N];
bool key=0;
inline int max(int x,int y){
if(x>y) return x;
return y;
}
inline void uper4(int x){
int l=0,k=a[x];
if(k==0) l=100000;
while(k>0){
k<<=1;
l++;
}
if(l>minn) return;
k<<=1;int l2=0;
if(k==0) l2=100000;
while(k>0){
k<<=1;
l2++;
}
k<<=1;int l3=0;
if(k==0) l3=100000;
while(k>0){
k<<=1;
l3++;
}
k<<=1;int l4=0;
if(k==0) l4=100000;
while(k>0){
k<<=1;
l4++;
}
if(l<minn){
minn=l;
minn2=l2;
minn3=l3;
minn4=l4;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
return;
}
else if(l==minn){
if(l2>minn2) return;
if(l2==minn2){
if(l3>minn3) return;
if(l3==minn3){
if(l4>minn4) return;
if(l4==minn4){
c[++cnt]=a[x];
d[cnt]=x;
}
else{
minn4=l4;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else if(l3<minn3){
minn3=l3;
minn4=l4;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn2=l2;
minn3=l3;
minn4=l4;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
return;
}
}
inline void uper6(int x){
int l=0,k=a[x];
if(k==0) l=100000;
while(k>0){
k<<=1;
l++;
}
if(l>minn) return;
k<<=1;int l2=0;
if(k==0) l2=100000;
while(k>0){
k<<=1;
l2++;
}
k<<=1;int l3=0;
if(k==0) l3=100000;
while(k>0){
k<<=1;
l3++;
}
k<<=1;int l4=0;
if(k==0) l4=100000;
while(k>0){
k<<=1;
l4++;
}
k<<=1;int l5=0;
if(k==0) l5=100000;
while(k>0){
k<<=1;
l5++;
}
k<<=1;int l6=0;
if(k==0) l6=100000;
while(k>0){
k<<=1;
l6++;
}
if(l<minn){
minn=l;
minn2=l2;
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
return;
}
else if(l==minn){
if(l2>minn2) return;
if(l2==minn2){
if(l3>minn3) return;
if(l3==minn3){
if(l4>minn4) return;
if(l4==minn4){
if(l5>minn5) return;
if(l5==minn5){
if(l6>minn6) return;
if(l6==minn6){
c[++cnt]=a[x];
d[cnt]=x;
}
else{
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn5=l5;
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn4=l4;
minn5=l5;
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else if(l3<minn3){
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn2=l2;
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
return;
}
}
inline void uper9(int x){
int l=0,k=a[x];
if(k==0) l=100000;
while(k>0){
k<<=1;
l++;
}
if(l>minn) return;
k<<=1;int l2=0;
if(k==0) l2=100000;
while(k>0){
k<<=1;
l2++;
}
k<<=1;int l3=0;
if(k==0) l3=100000;
while(k>0){
k<<=1;
l3++;
}
k<<=1;int l4=0;
if(k==0) l4=100000;
while(k>0){
k<<=1;
l4++;
}
k<<=1;int l5=0;
if(k==0) l5=100000;
while(k>0){
k<<=1;
l5++;
}
k<<=1;int l6=0;
if(k==0) l6=100000;
while(k>0){
k<<=1;
l6++;
}
k<<=1;int l7=0;
if(k==0) l7=100000;
while(k>0){
k<<=1;
l7++;
}
k<<=1;int l8=0;
if(k==0) l8=100000;
while(k>0){
k<<=1;
l8++;
}
k<<=1;int l9=0;
if(k==0) l9=100000;
while(k>0){
k<<=1;
l8++;
}
if(l<minn){
minn=l;
minn2=l2;
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
minn7=l7;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
return;
}
else if(l==minn){
if(l2>minn2) return;
if(l2==minn2){
if(l3>minn3) return;
if(l3==minn3){
if(l4>minn4) return;
if(l4==minn4){
if(l5>minn5) return;
if(l5==minn5){
if(l6>minn6) return;
if(l6==minn6){
if(l7>minn7) return;
if(l7<minn7){
if(l8>minn8) return;
if(l8==minn8){
if(l9>minn9) return;
if(l9==minn9){
c[++cnt]=a[x];
d[cnt]=x;
}
else{
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
else{
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn6=l6;
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn5=l5;
minn6=l6;
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn4=l4;
minn5=l5;
minn6=l6;
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
}
else{
minn2=l2;
minn3=l3;
minn4=l4;
minn5=l5;
minn6=l6;
minn7=l7;
minn8=l8;
minn9=l9;
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
}
return;
}
}
int main(){
freopen("data.in","r",stdin);
// freopen("and.out","w",stdout);
n=read();
for(register int i=1;i<=n;++i){
a[i]=read();if(a[i]!=a[i-1]&&i!=1) key=1;
}
if(!key){
printf("%d",a[1]);return 0;
}
if(n<=100005) for(register int i=1;i<=n;++i) uper4(i);//根据不同数据级别选择不同贪心精度,否则会T
else if(n<=2750001) for(register int i=1;i<=n;++i) uper6(i);
else for(register int i=1;i<=n;++i) uper9(i);
if(cnt==1){//防止被小数据卡
for(int i=1;i<=n;++i){
for(int j=i+1;j<=n;++j){
ans=max(ans,a[i]&a[j]);
}
}
}
else{
for(register int i=1;i<=cnt;++i){
for(register int j=i+1;j<=cnt;++j){
ans=max(ans,c[i]&c[j]);
}
}
}
printf("%d",ans);
return 0;
}
以下是当晚改进的版本
#include<cstdio>
#include<cstring>
#define N 300005
#define inf 0x7f7f7f7f
using namespace std;
inline int read(){
int e=0,ch=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-')ch=-1;c=getchar();}
while(c>='0'&&c<='9'){e=e*10+(c-48);c=getchar();}
return e*ch;
}
int n,cnt,ans,jie;
int minn[N],l[N];
int a[N],c[N],d[N];
bool key=0;
inline int max(int x,int y){
if(x>y) return x;
return y;
}
inline void uper(int x){
int num=1,k=a[x];
memset(l,0,sizeof l);
while(num<=jie){
if(k==0){
for(int i=num;i<=jie;++i) l[i]=10000;
}
while(k>0){
k<<=1;
l[num]++;
}
if(l[num]>minn[num]) return;
k<<=1;
num++;
}
num=1;
while(num<=jie){
if(l[num]>minn[num]) return;
if(l[num]<minn[num]){
for(int i=1;i<=jie;++i){
minn[num]=l[num];
}
cnt=1;
c[cnt]=a[x];
d[cnt]=x;
return;
}
num++;
}
c[++cnt]=a[x];
d[cnt]=x;
}
void init(){
memset(minn,inf,sizeof minn);
}
int main(){
freopen("and.in","r",stdin);
freopen("and.out","w",stdout);
n=read();
for(register int i=1;i<=n;++i){
a[i]=read();if(a[i]!=a[i-1]&&i!=1) key=1;
}
if(!key){
printf("%d",a[1]);return 0;
}
if(n<=1000) jie=0;
if(n<=100000) jie=3;
else if(n<=275001) jie=4;
else jie=5;
init();
if(jie^0) for(int i=1;i<=n;++i) uper(i);
if(cnt==1||jie==0){
for(register int i=1;i<=n;++i){
for(register int j=i+1;j<=n;++j){
ans=max(ans,a[i]&a[j]);
}
}
}
else{
for(register int i=1;i<=cnt;++i){
for(register int j=i+1;j<=cnt;++j){
ans=max(ans,c[i]&c[j]);
}
}
}
printf("%d",ans);
return 0;
}