hihocoder 1509 异或排序(模拟)

题目链接:http://hihocoder.com/problemset/problem/1509

解题方案:首先,两个数谁大谁小一定是看这两个数的高位里面第一个不相同的数字,不管是10进制还是2进制都是这样判断。然后可以将所有的a[i]看成是60位的二进制数,a[i]和a[i+1]二进制串相同的地方和s异或后一定还是一样的,不同的地方和s异或后一定还是不一样的,因为(0,1)^0=(0,1),(0,1)^1=(1,0),(0,0)^0=(0,0),(1,1)^1=(0,0)。所以s的二进制串若想满足题意,对a[i]和a[i+1]高位里面第一个不相同的位置j,s[j]是固定的。故只需要将s所有固定的位置的值求出来,期间判断一下是否出现矛盾,然后就可以算出符合题意的s的个数了。

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

using namespace std;

#define FOR(i,k,n) for(int i=k;i<n;i++)
#define FORR(i,k,n) for(int i=k;i<=n;i++)
#define scan(a) scanf("%d",&a)
#define scann(a,b) scanf("%d%d",&a,&b)
#define scannn(a,b,c) scanf("%d%d%d",&a,&b,&c)
#define mst(a,n)  memset(a,n,sizeof(a))
#define ll long long
#define N 65
#define mod 1000000007
#define INF 0x3f3f3f3f

const double eps=1e-8;
const double pi=acos(-1.0);

int a[N][N];
int s[N];

int main()
{
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);

    int n;
    while(cin>>n)
    {
        mst(a,0);
        mst(s,-1);
        FOR(i,0,n)
        {
            ll tmp;
            cin>>tmp;
            int cnt=0;
            while(tmp)
            {
                a[i][cnt++]=tmp&1;
                tmp>>=1;
            }
        }
        int flag=1;
        FOR(i,0,n-1)
        {
            if(!flag) break;
            for(int j=59;j>=0;j--)
            {
                if(a[i][j]!=a[i+1][j])
                {
                    if(a[i][j]==0&&a[i+1][j]==1)
                    {
                        if(s[j]==1)
                        {
                            flag=0;
                            break;
                        }
                        s[j]=0;
                    }
                    else
                    {
                        if(s[j]==0)
                        {
                            flag=0;
                            break;
                        }
                        s[j]=1;
                    }
                    break;
                }
            }
        }
        if(!flag) printf("0\n");
        else
        {
            int cnt=0;
            FOR(i,0,60) if(s[i]==-1) cnt++;
            //printf("%d\n",cnt);
            cout<< ((ll)(1)<<cnt) <<endl;
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值