标签:can cstring 关系 find 检索 names 位置 algorithm lower
链接:https://hihocoder.com/problemset/problem/1509
题意:异或排序
给定一个序列a[],给定一个函数 f(i) = a[i] XOR S, S为常数
问有多少个 0 <= S < 2^60 使得函数 f 为单调不减函数
(既然是中文题估计都能看得懂)
题解:
水题 ( 啪 x )
由于每一个数都有一个二进制表示,由数论知识我们知道比较两个数是从高位开始比较的,当比较到某一位发现一个数该位为1而另一个数该位为0时就知道前面那个数一定比后面那个要大,而再考虑异或的性质:
0 Xor 1 = 1
1 XOR 1 = 0
0 XOR 0 = 1
假设我们有两个数x,y,不妨设x>y,那么存在第i位使得x与y在更高的位都相等但是x在该位为1而y在该位为0,由于 1 XOR 1 = 0, 0 XOR 1 = 1,那么假若存在S,只要S在第i位为1,就能使得 (x XOR S) <= (y XOR S)
反正只要该位符合题意就好,其他位是任意的,显然这个任意的数目就是我们要求的了0。0思路大体也出来的
先生成一个S[60]的数组,扫描一遍,检索两个数是小大还是大小关系,小大关系的话在那个位置0,大小关系的话在那个位置成1,注意如果那位本来有数的话要看看是否一致,不一致说明这个东西他不存在
最后看看有多少个位置是没有被固定的,那么2的那个那个数目次方就是所求。
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
//stringstream ss(line)
#include<algorithm>
//sort(a,a+n,cmp)
//p=lower_bound(a,a+n,x)-a+1(大于或等于x的第一个位置)
#include<vector>
#include<bitset>
//bitset<N> xx
using namespace std;
typedef long long ll;
const int MAXN = 55;
const int MAXL = 65;
ll pow_[MAXL];
int im[MAXL];
ll num[MAXN];
ll quickPow(int k){
if(pow_[k]!=0) return pow_[k];
else return pow_[k] = quickPow(k/2)*quickPow(k-k/2);
}
int findHi(ll x){
int i;
for(i=60 - 1;i>=0;i--){
if(x>=quickPow(i)) break;
}
return i;
}
int main(){
memset(pow_,0,sizeof(pow_));
pow_[0]=1,pow_[1]=2;
quickPow(60);
memset(im,-1,sizeof(im));
int n;
scanf("%d",&n);
for(int i=0;i<n;i++) scanf("%lld",num+i);
ll temp;
int flag=-1;
for(int i=1;i<n;i++){
temp = num[i-1]^num[i];
flag=(num[i-1]>num[i]);
int ans = findHi(temp);
if(ans==-1) continue;
if(im[ans]==-1) im[ans]=flag;
else if(im[ans]!=flag){
printf("0");
return 0;
}
}
int sum=0;
for(int i=0;i<60;i++){
//printf("%d",im[i]);
if(im[i]==-1) sum++;
}
printf("%lld",quickPow(sum));
return 0;
}
标签:can cstring 关系 find 检索 names 位置 algorithm lower
原文地址:http://www.cnblogs.com/scidylanpno/p/6763737.html