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的位置的两种情况,‘
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#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; }
复杂度是logn