题目链接:点击打开链接
题目大意:
给定一个单调递增的数字序列,求每一个数字与其后面的数字中用二进制串表示时最多只有两个位置不同的数的数目。
解题思路:
这个题显然可以想到两种思路:
一:对于每一个数依次判断其后面的数是否满足条件,而总个数有2.5X1e5,显然TLE;
二:对于每一个数求:满足用二进制串表示时最多只有两个位置不同的数,然后判断这个数是否在给出的序列中,求和。因为用二进制串表示后最多只有18个位置,两个位置不同的 数量就是18*17/2,一个位置不同就是18个,这样的复杂度就不高了。求每一个数的时候,假如要改变某一个位置上的值,那么就将这一位与1进行异或。
代码:
#include<cstdio>
#include<cstring>
#include<string>
#include<map>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e6;
bool vis[maxn];
int a[maxn],ans;
inline bool scan_d(int &num){
char in;bool IsN=false;
in=getchar();
if(in==EOF) return false;
while(in!='-'&&(in<'0'||in>'9')) in=getchar();
if(in=='-'){ IsN=true;num=0;}
else num=in-'0';
while(in=getchar(),in>='0'&&in<='9'){
num*=10,num+=in-'0';
}
if(IsN) num=-num;
return true;
}
void solve(int x){
ans=0;
for(int i=0;i<18;i++){
for(int j=0;j<=i;j++){
int res=(1<<i);
res^=x;
if(i!=j)res^=(1<<j);
if(res>x&&vis[res]){
ans++;
}
}
}
printf("%d:%d\n",x,ans);
}
int main(){
// freopen("in.txt","r",stdin);
int cnt=0,num;
while(scan_d(num)){
if(num!=-1){
a[cnt++]=num;
vis[num]=1;
continue;
}
for(int i=0;i<cnt;i++)solve(a[i]);
cnt=0;memset(vis,0,sizeof vis);
}
return 0;
}
这个题应该写出来的呀
![抓狂](http://static.blog.csdn.net/xheditor/xheditor_emot/default/crazy.gif)
![哭](http://static.blog.csdn.net/xheditor/xheditor_emot/default/cry.gif)