整除分块
公式
求:\(\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
异或约数和
定义\(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;
}