[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;
}
posted @ 2020-05-10 18:20  Shawk  阅读(162)  评论(0编辑  收藏  举报