• [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;
    }
    
  • 相关阅读:
    API测试之Postman使用完全指南(Postman教程,这篇文章就够了)
    asp.net的webservice
    表和索引的结构(笔记)
    基于Nginx+PHP+Redis的短URL系统的实现 新风宇宙
    数据结构与算法(php版) 新风宇宙
    discuz7.2 昵称替换用户名 新风宇宙
    gVim7.3(Vim7.3)文本编辑器详细配置文件和配色方案 新风宇宙
    Discuz的Memcache缓存实现 新风宇宙
    GitHub使用(二) 从代码库下载代码到本地 新风宇宙
    PHPredis中文文档 新风宇宙
  • 原文地址:https://www.cnblogs.com/shawk/p/12864462.html
Copyright © 2020-2023  润新知