zoukankan      html  css  js  c++  java
  • [51nod1310]Chandrima and XOR

      有这样一个小到大排列的无穷序列S:1, 2, 4, 5, 8......,其中任何一个数转为2进制不包括2个连续的1。给出一个长度为N的正整数数组A,A1, A2......An记录的是下标(下标从1开始)。求S[A1] Xor S[A2] Xor S[A3] ..... Xor S[An]的结果(Xor 为异或运算),由于该数很大,输出Mod 1000000007的结果。

      例如:A = {1, 2, 3},对应S[1] = 1, S[2] = 2, S[3] = 4。1 Xor 2 Xor 4 = 7。
     Input
      第1行:1个数N,表示数组A的长度(1 <= N <= 50000)。
      第2 - N + 1行:每行一个数,对应数组A的元素A[i](1 <= A[i] <= 10^18)。
     Output
      输出一个数,S[A1] Xor S[A2] Xor S[A3] ..... Xor S[An]的结果Mod 1000000007。

      完全不会搞只能膜题解系列。

    实际上这道题可以通过O((logn)^2)的时间推出任意一项。

    我们以每一个2的整数次方作为分割点,把这个数列分割成很多块。设F(n)为2^n到2^(n+1)之间的所有满足要求的数字(不包括2^(n+1))。因为二进制中不能有连续的0,所以F(n)=sigma{F(k)|0<=k<=n-2}+1,又知F(n-1)=sigma{F(k)|0<=k<=n-3}+1,可得F(n)=F(n-2)+F(n-1)-1+1=F(n-1)+F(n-2),因此结论:

    有1个数在[1,2),1个数在[2,4),2个数在[4,8),3个数在[8,16)…………

    而每次可以用二分查找来确定a的位置在2^m和2^(m+1)之间,a减去[1,2^m]之间所有数的个数,重新递归查找。。。(注意减去的是闭区间!)递归深度不会超过logn,因为它是按斐波那契数列的和递减的。每一次递归的m位置异或1,最后会得到一个01数组,按照进制转换然后求模就行了。。

    一共有n个数,对于每一次查找的复杂度是O((logn)^2),总复杂度不会达到O(n(logn)^2)。

      讲道理那个查找是一个log的....

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<cstring>
     4 #include<algorithm>
     5 #include<queue>
     6 #include<cmath>
     7 #include<cstdlib>
     8 #include<bitset>
     9 //#include<ctime>
    10 #define ll long long
    11 #define ull unsigned long long
    12 #define ui unsigned int
    13 #define d double
    14 //#define ld long double
    15 using namespace std;
    16 const int maxn=233,modd=1000000007;
    17 ll pre[maxn],f[maxn],two[maxn];
    18 int i,j,k,n,m,MX;
    19 bool u[90];
    20 
    21 int ra,fh;char rx;
    22 inline int read(){
    23     rx=getchar(),ra=0,fh=1;
    24     while((rx<'0'||rx>'9')&&rx!='-')rx=getchar();
    25     if(rx=='-')fh=-1,rx=getchar();
    26     while(rx>='0'&&rx<='9')ra=ra*10+rx-48,rx=getchar();return ra*fh;
    27 }
    28 
    29 inline int get(ll x){
    30     int i;
    31     for(i=MX;i>0&&x>1;i--)if(x<=pre[i]&&x>pre[i-1])x-=pre[i-1]+1,u[i]^=1,i--;//,printf("   %d
    ",i);
    32     u[0]^=x>0;
    33 }
    34 int main(){
    35     f[0]=f[1]=1,two[0]=pre[0]=1,two[1]=pre[1]=2;
    36     for(i=2;i<=233;i++){
    37         f[i]=f[i-2]+f[i-1],two[i]=(two[i-1]<<1)%modd,
    38         pre[i]=pre[i-1]+f[i];
    39         if(pre[i]>1e18)break;
    40     }MX=i;
    41     
    42     n=read();ll a;int ans=0;
    43 //    for(i=1;i<=233;i++)printf("   %d
    ",get(i,MX));
    44     for(i=1;i<=n;i++)scanf("%lld",&a),get(a);
    45     for(i=0;i<=MX;i++)if(u[i])(ans+=two[i])%=modd;
    46     printf("%d
    ",ans);
    47 }
    View Code
  • 相关阅读:
    查看Ubuntu操作系统位数 Anny
    no such file to load zlib when using gem install Anny
    Error: shasum check failed for /tmp/npm1316662414557/13166624159930.13772299513220787/tmp.tgz Anny
    Future接口的应用
    ScheduledThreadPool
    弄了个群
    阻塞与中断
    获得CPU个数
    文件路径问题
    一个日志服务器的框架
  • 原文地址:https://www.cnblogs.com/czllgzmzl/p/5957544.html
Copyright © 2011-2022 走看看