Problem Statement
You are given a positive integer (N). Find the number of the pairs of integers (u) and (v(0≤u,v≤N))such that there exist two non-negative integers (a) and (b) satisfying (a xor b =u) and (a+b=v). Here, (xor) denotes the bitwise exclusive OR. Since it can be extremely large, compute the answer modulo (10^9+7).
Constraints
(1≤N≤10^{18})
Input
The input is given from Standard Input in the following format:
(N)
Output
Print the number of the possible pairs of integers (u) and (v), modulo (10^9+7).
Sample Input 1
3
Sample Output 1
5
The five possible pairs of (u) and (v) are:
- (u=0,v=0 ()Let $a=0,b=0, $ then (0 xor 0=0, 0+0=0.))
- (u=0,v=2 ()Let (a=1,b=1,) then (1 xor 1=0, 1+1=2.))
- (u=1,v=1 ()Let (a=1,b=0,) then (1 xor 0=1, 1+0=1.))
- (u=2,v=2 ()Let (a=2,b=0,) then (2 xor 0=2, 2+0=2.))
- (u=3,v=3 ()Let (a=3,b=0,) then (3 xor 0=3, 3+0=3.))
Sample Input 2
1422
Sample Output 2
52277
Sample Input 3
1000000000000000000
Sample Output 3
787014179
题解
题意
给出正整数N,求出整数对(u)和(v (0≤u,v≤N))的数目,
使得存在两个非负整数(a)和(b)满足(a xor b = u) 和(a + b= v)。
这里,(xor)表示按位异或。对答案取模(10^9 + 7)
解题思路
一上来直接懵逼,什么(xor),那就先打个表
#include <cstdio>
#include <cstring>
using namespace std;
const int N = 30;
int n = 20, num[N];
int main() {
for(int i = 0; i <= n; i++) {
int s = 0;
for(int u = 0; u <= i; u++) {
memset(num, 0, sizeof(num));
for(int a = 0; a <= u; a++) {
int b = u - a;
if ((a xor b) <= i) num[a xor b] = 1;
}
for(int j = 0; j <= i; j++)
if (num[j]) s++;
}
printf("a[%d] = %d,", i, s);
}
return 0;
}
打表的结果如下
a[0] = 1,a[1] = 2,a[2] = 4,a[3] = 5,a[4] = 8,a[5] = 10,
a[6] = 13,a[7] = 14,a[8] = 18,a[9] = 21,a[10] = 26,
a[11] = 28,a[12] = 33,a[13] = 36,a[14] = 40,a[15] = 41,
a[16] = 46,a[17] = 50,a[18] = 57,a[19] = 60,a[20] = 68,
设结果为(f_x)
经过各种操作白嫖,得到如下递推式:
- 当(x)为奇数,(f_x = 2 * f_{(x-1)/2} + f_{(x-1)/2-1})
- 当(x)为偶数,(f_x = f_{x/2} + 2 * f_{x/2-1})
由于数据是1e18的,不记忆化会超时
记忆化开数组会爆掉,就用了map来做记忆化
代码
#include <cstdio>
#include <map>
#define int long long
using namespace std;
const int M = 1e9+7;
map<int, int> a;
int n;
int dfs(int x) {
if (a[x]) return a[x];
if (x % 2) return a[x] = (2 * dfs(x / 2) + dfs(x / 2 - 1)) % M;
else return a[x] = (dfs(x / 2) + 2 * dfs(x / 2 - 1)) % M;
}
signed main() {
a[0] = 1; a[1] = 2;
scanf("%lld", &n);
printf("%lld", dfs(n));
return 0;
}