首页 > 代码库 > [hihoCoder]1509_异或排序
[hihoCoder]1509_异或排序
链接: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; }
[hihoCoder]1509_异或排序
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。