[ARC066B] Xor Sum —— 递归

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;
}
原文地址:https://www.cnblogs.com/Z8875/p/12864462.html