又是一个不眠之夜。

求:

\[f_i=1 \bigoplus 2 \bigoplus 3 \bigoplus...\bigoplus (i-1) \bigoplus i
\]

思路1:周期分析

\(O(logn)\)算法

考虑按位分析

对于\(f_i\)的第\(j\)位,它的值只与该位1出现次数有关。

而第\(j\)位1的出现又是呈周期性分布的。

我们考虑\(f_i=0 \bigoplus 1 \bigoplus 2 \bigoplus 3 \bigoplus...\bigoplus (i-1) \bigoplus i\)。

注意这里多加了一个0。

那么,在上式的各数中,第1位的变化为01010101

而第2位为00110011

第3位为00001111

以此类推。

周期分析

所以我们可以发现,第\(j\)位的值的出现是连续的,且每连续一组的相同值的个数为\(2^{j-1}\),这恰好是第\(j\)位的位权!

而对于数字的总个数,我们可以用\(x=i+1\)来表示。

分析第\(j\)位的值\((j \ge 2)\):

则第\(j\)位的出现的整组共有\(t=\lfloor{{x}\over{2^{j-1}}}\rfloor\)个,其中奇数组为0,偶数组为1,且其中出现数字1的总个数必定为偶数。

若\(t\)为奇数,说明剩余的不完整组的值为1,同时若\(x\)也为奇数,说明\(f_i\)的第\(j\)位为1;否则\(f_i\)的第\(j\)位为0。

由此,我们可以得到第\(j\)位的值\((j \ge 2)\)。

对于第1位,它出现的组共有\(x\)个,其中值为1的有\(\lfloor{{x}\over{2}}\rfloor\)个,故\(f_i\)的第1位等于\(x\)的第2位。

综上可以在\(O(logn)\)时间复杂度内求解。

\(O(1)\)算法

其实就是对\(O(logn)\)的算法作了一个小的总结。

分析第\(j\)位的值\((j \ge 2)\):

我们知道,当且仅当\(t = \lfloor{{x}\over{2^{j-1}}}\rfloor\)为奇数,同时\(x\)也为奇数时,第\(j\)位才为1;否则第\(j\)位为0。

体现在\(x\)这个数本身上,就是当\(x\)第1位为1时,\(f_i\)的第2位及以上与\(x\)的相同。

而当\(x\)第1位为0时,\(f_i\)的第2位及以上都为0。

然后第1位的特判很好处理,就是\(f_i\)的第1位等于\(x\)的第2位。

由此可以在\(O(1)\)时间复杂度内求解。

代码实现

闲来无事写个代码(因为太菜所以不会更简单的写法)

int xorsum(int x)
{
++x;
return ( (x&1) ? (x&(INT_MAX-1)) : 0 ) | ( (x&2) ? 1 : 0 );
}

数据检验

顺便学了一下二进制输出的方法

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<bitset> using namespace std; int xorsum(int x)
{
++x;
return ( (x&1) ? (x&(INT_MAX-1)) : 0 ) | ( (x&2) ? 1 : 0 );
} int main()
{
int n=10;
for(int i=1;i<=n;++i)
{
cout<<"number:"<<bitset<sizeof(i)*8>(i)<<'\n';
cout<<"xorsum:"<<bitset<sizeof(i)*8>(xorsum(i))<<'\n';
}
return 0;
}

输出如下:

思路2:数学化简

看了ltao思路和Limit给的正解,发现自己的做法实在是......太菜了。

一个很明显的劣势在于:我们的周期性分析是以\(x=i+1\)算出总数字个数再来分析性质的。

这样的转义分析最大的缺点就在于,性质推广,或者说移植的时候,会将定义转来转去,非常难以处理。

所以在这里再整理一下\(ltao\)的思路:

核心性质

定义\(g_{i,j}=i \bigoplus (i+1) \bigoplus ... \bigoplus j\)

有性质:\(g_{0,2^{k}-1} = g_{2^{k},2^{k+1}-1}(k \ge 1)\),即右式第\(k+1\)位全部被异或消掉

将左右两式异或可得:\(g_{0,2^{k+1}-1} = g_{0,2^{k}-1} \bigoplus g_{2^{k},2^{k+1}-1} = 0\)

得到核心性质:\(g_{0,2^{k-1}-1} = 0(k \ge 3)\),即可以用这个性质消掉函数中第\(k\)位为0的所有数,注意这个\(k\)的边界很重要!

\(O(logn)\)算法

有了这个性质,我们就可以很方便地对原式最高位进行化简,设所求函数\(g_{0,i}\)的\(i\)的最高位为\(k\),有:

\(g_{0,i} = g_{0, 2^{k-1}-1} \bigoplus g_{2^{k-1},i} = g_{2^{k-1},i}\)

然后组成\(g_{2^{k-1},i}\) 的数的第\(k\)位都为1,且共有\(m = i - 2^{k-1} + 1\)个这样的数

这样就可以化简掉第\(k\)位:

若\(i\)为奇数,则\(m\)为偶数,结果的第\(k\)位必然为0,即\(g_{2^{k-1},i} = g_{0,i-2^{k-1}}\);

若\(i\)为偶数,则\(m\)为奇数,结果的第\(k\)位必然为1,即\(g_{2^{k-1},i} = g_{0,i-2^{k-1}} + 2^{k-1}\)。

递归处理,至\(k \le 2\),达到了我们上面所说性质的边界以外,特判即可。

由此可以在\(O(logn)\)时间复杂度内求解。

\(O(1)\)算法

然后再对这个算法作一个小的总结:

我们可以发现上式的\(g_{0,i}-> g_{0,i-2^{k-1}}\)的过程当中,\(i\)的奇偶性始终不变。

因此只需一次分析起始状态\(g_{0,i}\):

若\(i\)为奇数,则\(m\)为偶数,结果的第3位及以上都为0。

若\(i\)为偶数,则\(m\)为奇数,结果的第3位及以上与\(i\)的相同。

剩下两位特判即可。

由此可在\(O(1)\)时间复杂度内完成求解。

代码实现

int f[4]={0,1,3,0};
int xorsum(int x)
{
return ( (x&1) ? 0 : (x&(INT_MAX-3)) ) | f[x&3];
}

或者更直观的写法:

int xorsum(int x)
{
switch(x&3)
{
case 0:
return x;
case 1:
return 1;
case 2:
return x+1;
case 3:
return 0;
}
}

非常重要的一点在于,这种直接将x&3的值和xorsum的值对应的直观函数表示,能够有效地解决一些扩展问题,有兴趣的可见这道基于Limit's idea的水题

O(1)求解自然数异或和的更多相关文章

  1. [笔记] 整除分块 & 异或性质

    整除分块 参考资料:整除分块_peng-ym OI生涯中的各种数论算法的证明 公式 求:\(\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor\) 对于每个\(\lfloo ...

  2. 【bzoj4671】异或图(容斥+斯特林反演+线性基)

    传送门 题意: 给出\(s,s\leq 60\)张图,每张图都有\(n,n\leq 10\)个点. 现在问有多少个图的子集,满足这些图的边"异或"起来后,这张图为连通图. 思路: ...

  3. poj1222(高斯消元法解异或方程组+开关问题)

    题目链接:https://vjudge.net/problem/POJ-1222 题意:给定一个5×6的01矩阵,改变一个点的状态时它上下左右包括它自己的状态都会翻转,因为翻转2次等价与没有翻转,那么 ...

  4. [总结]其他杂项数学相关(定理&证明&板子)

    目录 写在前面 一类反演问题 莫比乌斯反演 快速莫比乌斯变换(反演)与子集卷积 莫比乌斯变换(反演) 子集卷积 二项式反演 内容 证明 应用举例 另一形式 斯特林反演 第一类斯特林数 第二类斯特林数 ...

  5. (转载)solr时区问题解决方案

    solr默认的使用的是utc格林尼治时间,与我们的GMT+8相差8个小时,网上好多解决办法是在自己应用中的时间上加8个小时和减8个小时做变换:或者不用date类型,改为long. 个人感觉这两个办法都 ...

  6. CodeForces 703D Mishka and Interesting sum

    异或运算性质,离线操作,区间求异或和. 直接求区间出现偶数次数的异或和并不好算,需要计算反面. 首先,很容易求解区间异或和,记为$P$. 例如下面这个序列,$P = A[1]xorA[2]xorA[3 ...

  7. [AHOI2001]质数和分解

    [AHOI2001]质数和分解 题目描述 任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能有不止一种质数和的形 ...

  8. 洛谷 P2563 [AHOI2001]质数和分解

    洛谷  P2563 [AHOI2001]质数和分解 题目描述 任何大于 1 的自然数 n 都可以写成若干个大于等于 2 且小于等于 n 的质数之和表达式(包括只有一个数构成的和表达式的情况),并且可能 ...

  9. 【省选水题集Day1】一起来AK水题吧! 题目(更新到B)

    题解:http://www.cnblogs.com/ljc20020730/p/6937954.html 水题A: [AHOI2001]质数和分解 题目网址: https://www.luogu.or ...

随机推荐

  1. 小师妹学JavaIO之:文件系统和WatchService

    目录 简介 监控的痛点 WatchService和文件系统 WatchSerice的使用和实现本质 总结 简介 小师妹这次遇到了监控文件变化的问题,F师兄给小师妹介绍了JDK7 nio中引入的Watc ...

  2. Openshift 4.4 静态 IP 离线安装系列:准备离线资源

    本系列文章描述了离线环境下以 UPI (User Provisioned Infrastructure) 模式安装 Openshift Container Platform (OCP) 4.4.5 的 ...

  3. Js中Array 函数使用方法

    遇到数组有关操作,脑子第一反应不要再是嵌套 for 循环了,Array 类型提供了一些遍历有关的函数. Array.prototype.forEach() : 把数组每个元素丢到一个处理 functi ...

  4. 说说硬件中核心板的作用和优缺点,基于i.MX8M Mini核心处理器平台

    核心板,顾名思义,即硬件构成中关键的器件和电路打包封装的一块电子主板,具有布线复杂.多层.高频信号干扰.器件密度高等特性,大多数核心板集成了处理器.内存.存储器.电源管理和引脚,通过引脚与配套基板连接 ...

  5. Spring:BeanDefinition&PostProcessor不了解一下吗?

    水稻:这两天看了BeanDefinition和BeanFactoryPostProcessor还有BeanPostProcessor的源码.要不要了解一下 菜瓜:six six six,大佬请讲 水稻 ...

  6. python中的importlib包

    importlib.import_module(name, package=None) 导入一个模块.参数 name 指定了以绝对或相对导入方式导入什么模块 (比如要么像这样 pkg.mod 或者这样 ...

  7. Moco测试知多少?

    什么是mock? Mock就是在测试过程中,对于一些不容易构造/获取的对象,创建一个mock对象来替代它,帮助我们测试这种场景. 一般前端工程师会在后端工程师还没有完成后台接口开发的时候,自己根据事先 ...

  8. Java 多线程基础(八)线程让步

    Java 多线程基础(八)线程让步 yield 一.yield 介绍 yield()的作用是让步.它能让当前线程由“运行状态”进入到“就绪状态”,从而让其它具有相同优先级的等待线程获取执行权:但是,并 ...

  9. 拿来即用:用C+JS结构来处理JSON数据

    [面对的问题] 在物联网产品的开发过程中,对JSON格式的数据处理是一个强需求,例如亚马逊的 AWS IOT平台,设备与后台之间的通讯数据都是JSON格式,先瞄一眼大概的样子: 这是一个真实产品的通讯 ...

  10. loadRunnner中90%的响应时间

    参考博客https://blog.csdn.net/lengyue_112/article/details/1095320?utm_source=blogxgwz4 LR在场景执行完了会出个报告,其中 ...