一.取整函数的定义.
这里我们主要研究下取整函数,所以这里只定义下取整函数.
下取整函数:定义下取整函数⌊x⌋\lfloor x\rfloor⌊x⌋为:
⌊x⌋=maxi∈Z∧i≤x{i}
\lfloor x\rfloor=\max_{i\in Z\wedge i\leq x}\{i\}
⌊x⌋=i∈Z∧i≤xmax{i}
二.下取整函数的若干性质.
性质1:对于任意m∈N+m\in N_+m∈N+,有⌊⌊n⌋x⌋=⌊nx⌋\left \lfloor \frac{\left \lfloor n \right \rfloor}{x} \right \rfloor=\left \lfloor \frac{n}{x} \right \rfloor⌊x⌊n⌋⌋=⌊xn⌋.
证明:
设n=kx+rn=kx+rn=kx+r,其中n∈N+,r∈[0,x)n\in N_+,r \in [0,x)n∈N+,r∈[0,x).
⌊⌊n⌋x⌋=k+⌊⌊r⌋x⌋=k=k+⌊rx⌋=⌊nx⌋
\left \lfloor \frac{\left \lfloor n \right \rfloor}{x} \right \rfloor =k+\left \lfloor \frac{\left \lfloor r \right \rfloor}{x} \right \rfloor =k=k+\left \lfloor \frac{r}{x} \right \rfloor =\left \lfloor \frac{n}{x} \right \rfloor
⌊x⌊n⌋⌋=k+⌊x⌊r⌋⌋=k=k+⌊xr⌋=⌊xn⌋
证毕.
性质2:对于任意n∈N+n\in N_+n∈N+,⌊nx⌋\left \lfloor \frac{n}{x} \right \rfloor⌊xn⌋的取值只有最多2n2\sqrt{n}2n种,其中x∈N+x\in N_+x∈N+.
证明:
1.当x≤nx\leq \sqrt{n}x≤n时,发现k的取值最多只有n\sqrt{n}n种了,自然⌊nx⌋\left \lfloor \frac{n}{x} \right \rfloor⌊xn⌋的取值只有n\sqrt{n}n种.
2.当x>nx> \sqrt{n}x>n时,发现⌊nx⌋≤n\left \lfloor \frac{n}{x} \right \rfloor\leq \sqrt{n}⌊xn⌋≤n,所以下取整后的取值只有n\sqrt{n}n种.
综1,2所述,情况总共有2n2\sqrt{n}2n种.
证毕.
三.除法分块.
考虑下面的和式:
∑i=1nf(⌊ni⌋)
\sum_{i=1}^{n}f\left(\left\lfloor\frac{n}{i}\right\rfloor\right)
i=1∑nf(⌊in⌋)
假设我们能够O(1)O(1)O(1)计算f(n)f(n)f(n),则在O(n)O(n)O(n)的时间复杂度内就可以求出上面的式子.
但是我们如果不满足于这个速度呢?能不能更快?
根据性质2,我们发现⌊ni⌋\left\lfloor\frac{n}{i}\right\rfloor⌊in⌋只有O(n)O(\sqrt{n})O(n)种取值,而⌊ni⌋\left\lfloor\frac{n}{i}\right\rfloor⌊in⌋相同时,它们对应的f(⌊ni⌋)f(\left\lfloor\frac{n}{i}\right\rfloor)f(⌊in⌋)也是相等的,也就是说f(⌊ni⌋)f(\left\lfloor\frac{n}{i}\right\rfloor)f(⌊in⌋)也只有O(n)O(\sqrt{n})O(n)种取值.
但是我们如何确定每种⌊ni⌋\left\lfloor\frac{n}{i}\right\rfloor⌊in⌋出现了多少次呢?
显然当kkk确定时,所有满足⌊ni⌋=k\left\lfloor\frac{n}{i}\right\rfloor=k⌊in⌋=k的iii是一个区间,现在问题是如何求出区间的两个端点.
我们考虑一个做法,首先第一个区间的左端点必然为111,而求出了右端点后,下一个区间就是这个区间的右端点+1+1+1了.
现在问题只剩下如何用左端点推出右端点了.
假设此时左端点为lll,右端点为rrr,那么有⌊nl⌋=⌊nr⌋\left\lfloor\frac{n}{l}\right\rfloor=\left\lfloor\frac{n}{r}\right\rfloor⌊ln⌋=⌊rn⌋,且lll最小而rrr最大,即nl\frac{n}{l}ln最大而nr\frac{n}{r}rn最小.显然此时就有:
r=⌊n⌊nl⌋⌋
r=\left\lfloor\frac{n}{\left\lfloor\frac{n}{l}\right\rfloor}\right\rfloor
r=⌊⌊ln⌋n⌋
代码如下:
int Div_block(int n){
int res=0;
for (int l=1,r;l<=n;l=r+1){
r=n/(n/l);
res+=(r-l+1)*f(n/l);
}
return res;
}
四.类欧几里得算法.
咕.