zoukankan      html  css  js  c++  java
  • 51nod-1310: Chandrima and XOR

    【传送门:51nod-1310


    简要题意:

      有一个数组S,保证里面的数是从小到大的,而且每一个数的二进制中都没有连续的1,如:1,2,4,5,8...

      给出n,然后给出n个位置,求出S数组中n个位置的异或和


    题解:

      数位DP好题,卡了老久

      设f[i]表示2i-1到2i-1中有多少个数是在数组S中的

      转移很容易想到$f[i]=1+sum_{j=1}^{i-2}f[j]$

      而也可以得到$f[i-1]=1+sum_{j=1}^{i-3}f[j]$

      上下两式合并得到$f[i]=f[i-1]+f[i-2]$

      就是斐波那契数列,f[1]=f[2]=1

      设s[i]为1到2i-1中有多少个数是在数组S中的,显然$s[i]=sum_{j=1}^{i}f[j]$

      然后就可以做了,对于一个位置x,二分找到最大的小于x的s[m],将x-s[m]-1后再进行递归二分,复杂度为O((logn)2)

      只要在途中维护异或就行了,设P[i]为答案二进制中第i位的数,对于找到的m,将P[m]^=1就好了

      最后转换成二进制就行了,注意可能在算2的次方的时候会爆long long,所以要用快速幂


    参考代码:

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long LL;
    int P[310],tot;
    LL a[51000],Mod=1e9+7;
    LL f[310],s[310];
    void pre()
    {
        tot=2;
        f[1]=1;f[2]=1;
        s[1]=1;s[2]=2;
        for(tot=3;;tot++)
        {
            f[tot]=f[tot-2]+f[tot-1];
            s[tot]=f[tot]+s[tot-1];
            if(s[tot]>1e18) break;
        }
    }
    void getp(LL x)
    {
        if(x==0) return ;
        int l=0,r=tot,m;
        while(l<=r)
        {
            int mid=(l+r)/2;
            if(x>s[mid]) m=mid,l=mid+1;
            else r=mid-1;
        }
        P[m]^=1;
        getp(x-s[m]-1);
    }
    LL p_mod(LL a,LL b)
    {
        LL ans=1;
        while(b!=0)
        {
            if(b%2==1) ans=ans*a%Mod;
            a=a*a%Mod;b/=2;
        }
        return ans;
    }
    int main()
    {
        pre();
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%lld",&a[i]);
            getp(a[i]);
        }
        LL ans=0;
        for(int i=0;i<=tot;i++) ans=(ans+LL(P[i])*p_mod(2,i))%Mod;
        printf("%lld
    ",ans);
        return 0;
    }

     

  • 相关阅读:
    Linux-安装FFmpeg
    博客园添加视频
    博客园添加音乐
    通过容器提交镜像(docker commit)以及推送镜像(docker push)笔记
    根据不同配置.env获取不同的配置文件的配置
    1M大概多少个字
    计算机存储单位
    DNS原理及其解析过程
    查看到百度经过了多少个网关
    C语言的本质(18)——函数的可变参数
  • 原文地址:https://www.cnblogs.com/Never-mind/p/9776322.html
Copyright © 2011-2022 走看看