数论分块
数论分块
对于一类含有\(\lfloor \frac{𝑛}{i} \rfloor\)的求和式 (𝑛 为常数),由于\(\lfloor \frac{𝑛}{i} \rfloor\)单调不增,故存在多个区间[𝑙,𝑟], 使得\(\lfloor \frac{𝑛}{i} \rfloor\)=\(\lfloor \frac{𝑛}{j} \rfloor\) (𝑖,𝑗∈[𝑙,𝑟]) 成立。
对于任意一个𝑖,最大的满足上式的 𝑗=\(\lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
证明
\(\lfloor \frac{𝑛}{i} \rfloor \leqslant\frac{𝑛}{i}\)
\(\Rightarrow \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor \geqslant \lfloor {\frac{n}{ \frac{𝑛}{i} } }\rfloor =\lfloor i \rfloor=i\)
\(\Rightarrow i \leqslant \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} } \rfloor
\)
即\(j= \lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)
\(\\\)
\(\\\)
\(\\\)
\(\\\)
例题
经典题 P1403 [AHOI2005]约数研究
题意:
\(f(x)\)表示x的约数个数,求\(\sum_{i=1}^nf(i)\)
思路:
对于\(i\),在\(1~n\)中,他的倍数有\(\lfloor \frac{𝑛}{i} \rfloor\)个,因此\(1~n\)中共有个以\(i\)为约数的数。
因此\(\sum_{i=1}^nf(i)=\sum_{i=1}^n\lfloor \frac{𝑛}{i} \rfloor\)
现在考虑数论分块
对于每一个l∈[1,n],存在区间[l,r],\(r=\lfloor {\frac{n}{\lfloor \frac{𝑛}{i} \rfloor} }\rfloor\)
使得\(\lfloor \frac{𝑛}{i} \rfloor\)=\(\lfloor \frac{𝑛}{j} \rfloor\)
区间贡献\((r-l+1)\times \lfloor \frac{𝑛}{i} \rfloor\).
\(O(2\sqrt n)\)
int n;
signed main()
{
n=rd;
int ans=0;
for(int i=1,j=1;i<=n;i=j+1)
{
j=n/(n/i);
ans+=(j-i+1)*(n/i);
}
printf("%lld\n",ans);
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
[CQOI2007]余数求和
思路:
int k,n;
signed main()
{
n=rd,k=rd;
int ans=n*k;
for(int i=1,j=1;i<=n;i=j+1)
{
if(k/i==0) break;
j=min(n,k/(k/i));
ans-=(k/i)*(j+i)*(j-i+1)/2;
}
printf("%lld\n",ans);
return 0;
}
\(\\\)
\(\\\)
\(\\\)
\(\\\)
P2424 约数和
int x,y;
int f(int a)
{
int ans=0;
for(int i=1,j=1;i<=a;i=j+1)
{
j=a/(a/i);
ans+=(a/i)*(i+j)*(j-i+1)/2;
}
return ans;
}
signed main()
{
x=rd,y=rd;
printf("%lld\n",f(y)-f(x-1));
return 0;
}