Sum vs XOR

https://www.hackerrank.com/contests/hourrank-13/challenges/arthur-and-coprimes

要求找出所有x <= n   x + n = x ^ n的个数。

首先如果n的二进制是100101010  n = 298

这样的话

先考虑最高位的1,如果x在同一个位上也是1,就是x是100000000这样的话,是不行的,因为异或并不能使那一位变成0,而加法却把他们变了(进位了),所以,如果那个固定是1,那么x从100000000 --- 100101010都是不行的

考虑第二个1,同样道理,如果这位是1,那么其它的无论怎么取也不行。

那么现在问题就是转化为:在这么多个1中,任选若干个固定,其他的0任取什么值也没问题,有多少种方案。、

怎么算是任选若干个呢,那么先考虑固定第二个1,然后往左统计0的个数(不统计1的个数),右边的全部当作0.

这样贡献 +pow(2, len)。然后枚举第三个1,一路做下去即可

这个时候如果左边还有1,那么只能在那位放0了,因为前面枚举那个位固定为1的时候,已经考虑了后面那些1的位置的两种情况,‘

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;

#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const LL one = 1;
char str[111];
int lenstr;
void bin(LL n) {
    if (n / 2) {
        bin(n / 2);
    }
    str[lenstr++] = n % 2 + '0';
}
void work() {
//    int n;
//    cin >> n;
//    int ans = 0;
////    cout << n << endl;
//    for (int i = 0; i <= n; ++i) {
//        int t = n ^ i;
////        cout << t << " fff" << endl;
//        if (t == n + i) ++ans;
//    }
//    cout << ans << endl;
    LL n;
    cin >> n;
    LL ans = 0;
    for (int i = 62; i >= 0; --i) {
        if ((n & (one << i)) > 0) {
            ans += n - (one << i) + 1;
            break;
        }
    }
    bin(n);
    for (int i = 1; i < lenstr; ++i) {
        if (str[i] == '1') {
            int t = lenstr - 1 - i;
            for (int j = i - 1; j > 0; --j) {
                if (str[j] == '0') t++;
            }
            ans += pow(2, t);
        }
    }
    cout << n + 1 - ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt","r",stdin);
#endif
    work();
    return 0;
}
View Code

复杂度是logn

 

posted on 2016-10-05 02:13  stupid_one  阅读(226)  评论(0编辑  收藏  举报

导航