hiho1509 异或排序

题目链接

题目大意:

给定一个长度为 n 的非负整数序列 a[1..n]

你需要求有多少个非负整数 S 满足以下两个条件:

(1).0 ≤ S < 260

(2).对于所有 1 ≤ i < n ,有 (a[i] xor S) ≤ (a[i+1] xor S)

1 ≤ n ≤ 50

0 ≤ a[i] < 260

-------------------------------------------------------------------------------------

开始看到题感觉无从下手,分析了一下才发现是到水题。

维护一个60位的标记数组,用来表示S的第i位可以放置的数(11为置01都可,01为只可置0,10为只可置1,00为都不能放)。初始状态为11。

开始时n个数在一个组内,要满足条件(2),n个数的最高位必须满足

1)全部为0或1;这时候该位可以放0或者1。

2)前几个数最高位为0,后面的数为1.(或者反过来),但不会出现01交替出现的情况;这时候该位只能放0或者1.

对于情况1)仍把改组扔到次高位处理。

对于情况2)可以把该组分成两组扔到次高位处理。

#include <set>
#include <map>
#include <stack>
#include <queue>
#include <cmath>
#include <vector>
#include <string>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

#define MAX(a,b) ((a)>=(b)?(a):(b))
#define MIN(a,b) ((a)<=(b)?(a):(b))
#define OO 0x0fffffff
using namespace std;
typedef long long LL;
const int N = 66;
int digits[N][N];
void getDigits(int id,LL data){
    for(int i=0;i<60;i++){
        digits[id][i]=(data&1L);
        data>>=1;
    }
}
int choice[N];
int n;
LL data;
struct Node{
   int level;
   int spos,epos;
   int sdigit,scnt;
   Node(int tlevel,int tspos,int tepos){
       level = tlevel;
       spos = tspos;
       epos = tepos;
   }
   Node(){}
   int length(){
       return epos-spos+1;
   }
};
int main(){
    cin>>n;
    for(int i=0;i<n;i++) {
       cin>>data;
       getDigits(i,data);
    }
    for(int i=0;i<60;i++) choice[i] = 3;

    Node head(59,0,n-1);
    queue<Node> q;
    q.push(head);
    while(!q.empty()){
        Node cur = q.front(); q.pop();
        cur.sdigit = digits[cur.spos][cur.level];
        cur.scnt = 1;
        for(int r=cur.spos+1;r<=cur.epos;r++){
            if(digits[r][cur.level]==digits[r-1][cur.level])
                cur.scnt++;
            else break;
        }
        if(cur.scnt==cur.length()){
            choice[cur.level]&=3;
            if(cur.level)
                q.push(Node(cur.level-1,cur.spos,cur.epos));
        }
        else {
            choice[cur.level]&=(cur.sdigit+1);
            if(cur.level){
                q.push(Node(cur.level-1,cur.spos,cur.spos+cur.scnt-1));
                q.push(Node(cur.level-1,cur.spos+cur.scnt,cur.epos));
            }
        }
    }
    LL ans = 1;
    for(int i=0;i<60;i++){
        if(!choice[i]) {
            ans=0;
            break;
        }
        if(choice[i]==3) ans*=2;
    }
    printf("%lld\n",ans);
    return 0;
}
时间: 2024-10-08 16:58:15

hiho1509 异或排序的相关文章

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 输出 一个非负正数,表示答

[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.异或排序(位运算 思路)

题目链接 \(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\)

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 输出 一个非负正数,表

DSA Range

最近开学了,又复习了下数据结构与算法,我在MOOC上学的.这次是清华oj平台上的一题. 题目:范围查询(Range) Descriptioin Let S be a set of n integral points on the x-axis. For each given interval [a, b], you are asked to count the points lying inside. Input The first line contains two integers: n (

April Fools Contest 2017 题解&amp;源码(A,数学 B,数学 C,数学 D,字符串 E,数字逻辑 F,排序,卡时间)

A. Numbers Joke time limit per test:2 seconds memory limit per test:64 megabytes input:standard input output:standard output Input The input contains a single integer a (1 ≤ a ≤ 30). Output Output a single integer. Example Input 3 Output 27 题目链接:http

排序算法总结之插入排序

一,插入排序介绍 插入排序是基于比较的排序.所谓的基于比较,就是通过比较数组中的元素,看谁大谁小,根据结果来调整元素的位置. 因此,对于这类排序,就有两种基本的操作:①比较操作: ②交换操作 其中,对于交换操作,可以优化成移动操作,即不直接进行两个元素的交换,还是用一个枢轴元素(tmp)将当前元素先保存起来,然后执行移动操作,待确定了最终位置后,再将当前元素放入合适的位置.(下面的插入排序就用到了这个技巧)--因为,交换操作需要三次赋值,而移动操作只需要一次赋值! 有些排序算法,比较次数比较多,

java实现AOV图的拓扑排序

拓扑排序作为图的应用,了解拓扑排序必须首先了解AOV图. AOV网表示一个有向图中顶点,用弧表示顶点之间的优先关系.如下图所示,在AOV网中,若从顶点vi到顶点vj之间存在一条有向路径,则称顶点vi为顶点vj的前驱,顶点vj为顶点vi的后继.注意,AOV图不能有回路,否则会将序列陷入死循环,称为死锁. 进行拓扑排序,一般步骤如下: <1>在AOV网中选择一个入度为0的顶点 <2>在AOV网中删除此顶点及其相连的有向边 <3>重复步骤<1>和<2>

UVa 11039 (排序+贪心) Building designing

白书上的例题比较难,认真理解样例代码有助于提高自己 后面的练习题相对简单,独立思考解决问题,增强信心 题意:n个绝对值各不相同的非0整数,选出尽量多的数排成序列,使得该序列正负交错且绝对值递增. 解法:先按绝对值从小到大排序,然后第一个数先入队,然后依次比较后面的数,如果和队尾的数符号相反则入队,直到所有的数遍历完为止 这里用了异或运算,因为这里面没有0,所谓符号相同的两个数异或值为正,不同符号的数异或值为负 1 //#define LOCAL 2 #include <algorithm> 3