zoukankan      html  css  js  c++  java
  • xor_sum,题解

    题目:

    题意:

      找到满足u<=n,v<=n,且存在a xor b=u,a+b=v,的数对(u,v)的个数。

    分析:

      n很大,挨个递推就不太好了,不过我们先想一想可以怎么稍微暴力点的递推:fi=fi-1+Coi,也就是一个一个来,Coi表示和为i的有多少个异或之后有多少结果。当然,这样复杂度是无法接受的。数组开不下,来个递归处理,当然函数也占地方。

      都想到递归了,想一想有什么别的递归方式,有的,fi=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),为什么呢?首先先证明下界,即fi>=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),我们尝试构造,我们给得到i/2以内的数对x1,y1的数字a1,b1,最后一位(二进制为)补一个0,新的到的数字a,b,那么有,a+b<=n,a xor b<=n,且不会重复,我们给得到(i-1)/2以内的数对的数字补1和0,同样可以得到新的数字和数对,且不重,同样,给(i-2)/2以内的补两个1,同样不重,且三组里的数对没有重复。为什么呢?首先末尾补0,1的一定和另两个组不同,而补0,0和补1,1的异或如果想等,那么倒数第二位的和相等,但是由于1,1进位,所以和的倒数第二位将不会想等,于是有fi>=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),然后证明上界,即fi<=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),类似的方法,给这些数字最后一位抹掉,发现新的数对数量不会超过f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整)。于是我们有了fi<=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),于是有fi=f(i/2)+f((i-1)/2)+f((i-2)/2)(除法向下取整),当然,为了快一点,我们会合并一下(分奇偶),然后没次递归就只调用两个函数(其实调用3个也差不多,因为将会有两个一样),然后再记忆化一下。

      最后复杂度的证明:需要处理出的数最多有:x,x/2,x/2-1,x/4,x/4-1,x/4-2,x/8,x/8-1,x/8-2,x/8-3,所以复杂度应该是(logn)的平方,然后就是代码。

    #include <cstdio>
    #include <map>
    const int mod=1e9+7;
    using namespace std;
    map<long long,int> ma;
    int Cl(long long x){
        if(ma[x])
            return ma[x];
        if(x&1)
            return ma[x]=((long long)Cl(x/2ll)*2ll+Cl(x/2ll-1ll))%mod;
        return (Cl(x/2ll-1ll)*2ll+Cl(x/2ll))%mod;
    }
    int main(){
        long long n;
        scanf("%lld",&n);
        ma[0]=1;
        ma[1]=2;
        ma[2]=4;
        ma[3]=5;
        ma[4]=8;
        printf("%d",Cl(n));
        return 0;
    }
  • 相关阅读:
    编译资源收集
    volatile和synchronized到底啥区别?多图文讲解告诉你
    沙雕与大婶 | Mock掉你的外部依赖吧
    全网最详细的一篇Flutter 尺寸限制类容器总结
    一篇带你看懂Flutter叠加组件Stack
    【MySQL】:事务四大特性与隔离级别
    Dubbo 入门-细说分布式与集群
    Java 线程基础知识
    SpringBoot图文教程9—SpringBoot 导入导出 Excel 「Apache Poi」
    搭建博客、自己的小窝?快来看看这些开源静态网站生成器
  • 原文地址:https://www.cnblogs.com/wish-all-ac/p/12865183.html
Copyright © 2011-2022 走看看