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

整除分块

参考资料:整除分块_peng-ym
OI生涯中的各种数论算法的证明

公式

求:\(\sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor\)

对于每个\(\lfloor\frac{n}{i}\rfloor\)值相同的区间\([l,r]\)\(r=n/(n/l)\),即对于\(\forall x\in [i,n/(n/i)]\)\(x=\lfloor\frac{n}{i}\rfloor\).

时间复杂度

\(O(\sqrt{n})\)

代码

for(int l = 1, r; l <= n; l = r + 1)
{
    r = n / (n / l);
    ans += (r - l + 1) * (n / l);
}

异或性质

参考资料:

求一段连续自然数的异或结果

自然数异或前缀和

\[\bigoplus_{i=1}^{n} =\begin{cases}1, n\bmod4=1\\x+1, n\bmod4=2 \\0, n\bmod4=3\\x, n\bmod4=0\end{cases} \]

Problem

异或约数和

51nod

定义\(f(i)\)\(i\)的所有约数的异或和,给定\(n(1\leq n\leq 10^{14})\),求 \(f(1)xorf(2)xorf(3)xor...xorf(n)\)(其中\(xor\)表示按位异或)

先推出$$Ans=\bigoplus_{i=1}^{n}i ,(n/i)\bmod 2=0$$

用整除分块和异或前缀和

#include <iostream>
#include <cstdio>
#define ll long long

using namespace std;
ll ans, n;
ll f(ll x) {
	if(x % 4 == 1) return 1LL;
	if(x % 4 == 2) return x + 1LL;
	if(x % 4 == 3) return 0LL;
	if(x % 4 == 0) return x;
}
int main()
{
	cin >> n;
	for(ll l = 1, r; l <= n; l = r + 1)
	{
		r = n / (n / l);
		if((n / l) % 2 == 1) ans ^= f(r) ^ f(l - 1);
	}
//	for(int i = 1; i <= n; i++)
//		ans ^= (n / i) % 2 == 0 ? 0 : i;
	cout << ans << endl;
	return 0;
}
posted @ 2019-01-13 10:11  Shiokiri  阅读(376)  评论(0编辑  收藏  举报