XOR Groups

题目要求:

给出一个整数组数 A ,大小为N。然后,将数组 A 分割为两个部分A1 A2 ,且满足条件 A1A2= A1A2=A A1,A2 。计算有多少种分割方法,使得 Xor(A1)=Xor(A2) 。其中, Xor(A1)= all elements xor in A1

问题分析:

有两种不同的解题角度,搜索解和构造解。当 N 很大时,本题显然要用构造解的方法。因为所有所有分割方法,再进行判断的方法非常耗时,那是天文数字。因此,我们可以从下面的式子恒成立角度思考:

Xor(A)=Xor(A1)Xor(A2)

其中, 表示异或运算符。这个式子使用了异或运算的结合律性质。

进一步,如果两个数的异或结果为0,说明这两个数相等。反之,也成立

因此,我们有一个结论:
只要存在一种满足题意的分割方法,那么对于数组 A 来说总共存在2N22中分割方法。也是说题目的解为下式

=2N22ifXor(A)=0

=0ifXor(A)0

如果 Xor(A)0 ,那么根据异或运算的结合律可知,任何两部分的异或结果再异或都不为0( Xor(A1)Xor(A2)=Xor(A)0 ),即两部分的异或结果不相等,不存满足题意的分割。

hackrank上一道题:Xor Group

#include <cmath>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;

const int m = 1e9 + 7;

long long myPow(long long base, long long n){
    if( n == 0 )
        return 1;
    return ( myPow(base*base%m, n/2) * (n%2==0? 1: base) ) % m;
}

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int N;
    scanf("%d", &N);
    int x(0), v;
    for(int i = 0; i < N; ++i){
        scanf("%d", &v);
        x ^= v;
    }

    if( x != 0 ){
        printf("0\n");
    }
    else{
        printf("%d\n", myPow(2, N-1) - 1 );
    }

    return 0;
}

为了加快速度,我们使用时间复杂度为 O(log(N)) 的快速求幂方法,在《挑战程序设计》第2.4小节有其实现依据。此处的幂运算带有模运算,因为幂运算的结果会非常大,所以选择 1e9+7 作为模值。在幂运算中一定对每一处乘法运算的结果取模,且用 longlong 类型存储数据。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值