hihoCoder.1509.异或排序(位运算 思路)

题目链接

\(Description\)

给定长为\(n\)的序列\(A\)。求有多少\(S\),满足\(0\leq S<2^{60}\),且对于所有\(i\in[1,n-1]\),\(a[i]^{\wedge}S\leq a[i+1]^{\wedge}S\)。
\(n\leq20\)。

\(Solution\)

考虑对于\(a,b\),有哪些\(S\)满足\(a^{\wedge}S\leq b^{\wedge}S\)。
找出\(a^{\wedge}b\)的最高位\(1\)(也就是\(a,b\)不同的最高位),如果这一位\(a\)是\(0\),\(b\)是\(1\),那么\(S\)这一位必须是\(0\);否则\(S\)这一位必须是\(1\)。
所以每个\(a[i]^{\wedge}S\leq a[i+1]^{\wedge}S\)实际上是限制了\(S\)的某一位。把所有限制算出来就行了。

//0ms   0MB
#include <cstdio>
#include <cctype>
#include <cstring>
#include <algorithm>
#define gc() getchar()
#define BIT 59
typedef long long LL;
const int N=66;

int ban[N];

inline LL read()
{
    LL now=0;register char c=gc();
    for(;!isdigit(c);c=gc());
    for(;isdigit(c);now=now*10+c-'0',c=gc());
    return now;
}

int main()
{
    memset(ban,0xff,sizeof ban);
    int n=read(); LL las=read();
    for(int i=2; i<=n; ++i)
    {
        LL now=read(),s=now^las;
        for(int j=BIT; ~j; --j)
        {
            if(!(s>>j&1)) continue;
            if(las>>j&1)
                if(!ban[j]) return puts("0"),0;
                else ban[j]=1;
            else
                if(ban[j]==1) return puts("0"),0;
                else ban[j]=0;
            break;
        }
        las=now;
    }
    LL ans=1;
    for(int i=BIT; ~i; --i) if(ban[i]==-1) ans<<=1ll;
    printf("%lld\n",ans);

    return 0;
}

原文地址:https://www.cnblogs.com/SovietPower/p/9784455.html

时间: 2024-10-10 00:58:57

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时就知道前面那个数一定比后面那个要大,而

HihoCoder - 1509 XOR Sorting

#1509 : 异或排序 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个长度为 n 的非负整数序列 a[1..n] 你需要求有多少个非负整数 S 满足以下两个条件: (1).0 ≤ S < 260 (2).对于所有 1 ≤ i < n ,有 (a[i] xor S) ≤ (a[i+1] xor S) 输入 第一行一个正整数 n 第二行 n 个非负整数表示序列 a[1..n] 1 ≤ n ≤ 50 0 ≤ a[i] < 260 输出 一个非负正数,表

【宋红康程序思想学习日记1】运用位运算思想实现两个数的互换

/** 位运算思路的一些解决办法. 交换m=12与n=5的值.*/class WeiExercise1{ public static void main(String[] args) { //方法一 /*int temp=0; int m=12; int n=5; temp=m; m=n; n=temp;*/ //方法二 /*int m=12; int n=5; m+=n; n=m-n; m=m-n;*/ //方法三 位运算 (m^n)^m==n,(m^n)^m==n int m=12;// 1

杭电 2095 find your present (2)【位运算 异或】

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2095 解题思路:因为只有我们要求的那个数出现的次数为奇数,所以可以用位运算来做,两次异或同一个数最后结果不变,那么就可以知道异或运算相当于过滤掉了出现次数为偶数的数,最后只留下了唯一的那一个出现次数为奇数的数. 反思:位运算好陌生,好好学. #include<stdio.h> int main() { int n; long int a; while(scanf("%d",&a

位运算之 C 与或非异或

位运算比较易混: 位运算之 C 与或非异或 与运算:& 两者都为1为1,否则为0 1&1=1,  1&0=0,  0&1=0,  0&0=0 或运算:| 两者都为0为0,否则为1 1|1 = 1,  1|0 = 1,  0|1 = 1, 0|0 = 0 非运算:~ 1取0,0取1 ~1 = 0, ~0 = 1 ~(10001) = 01110 异或运算:^ 两者相等为0,不等为1(易混淆) 1^1=0, 1^0=1, 0^1=1, 0^0=0 位移操作符:<&

位运算常用操作总结位运算应用口诀清零取反要用与,某位置一可用或若要取反和交换,轻轻松松用异或移位运

来源:http://www.educity.cn/wenda/381487.html 位运算常用操作总结位运算应用口诀 清零取反要用与,某位置一可用或 若要取反和交换,轻轻松松用异或 移位运算 要点 1 它们都是双目运算符,两个运算分量都是整形,结果也是整形.     2 " $amp;     3 "$amp;>amp;>quot;$右移:右边的位被挤掉.对于左边移出的空位,如果是正数则空位补0,若为负数,可能补0或补1,这取决于所用的计算机系统.     4 "

137.Single Number II(法1排序法2STL容器map哈希法3位运算法4改进的位运算)

Given an array of integers, every element appears three timesexcept for one. Find that single one. Note: Your algorithm should have a linear runtime complexity. Could you implement itwithout using extra memory? HideTags Bit Manipulation #pragma once

hihoCoder挑战赛28 题目1 : 异或排序

题目1 : 异或排序 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个长度为 n 的非负整数序列 a[1..n] 你需要求有多少个非负整数 S 满足以下两个条件: (1).0 ≤ S < 260 (2).对于所有 1 ≤ i < n ,有 (a[i] xor S) ≤ (a[i+1] xor S) 输入 第一行一个正整数 n 第二行 n 个非负整数表示序列 a[1..n] 1 ≤ n ≤ 50 0 ≤ a[i] < 260 输出 一个非负正数,表示答

C的|、||、&amp;、&amp;&amp;、异或、~、!运算 位运算

研究这个的起因是我遇到一个题目,判断一个数是奇偶数,这个很简单,但是又个最佳代码 判断奇偶时用了 #include int main() { int n; scanf("%d",&n); printf("%s",n&1?"odd":"even"); } 这里用&运算,从而判断二进制数的最后一位是否为当n的最后一位=0.和1& 则为 0 .只有当n = 1 则 &为 1 再根据?:表达式的