整除(数论)分块个人小记

problem: P1403 [AHOI2005] 约数研究

题目稍微变换一下,就是让你求 $\sum\limits_{i=1}^{n} \left \lfloor \frac{n}{i} \right \rfloor $ 这一个式子。

于是一眼整除分块,虽然忘了怎么打,但凭借莫比乌斯反演的经验调了半个小时调对了……

现在终于懂了:
对于一个端点 \(l\) ,求出最远的 \(r\) 使得 \(\left \lfloor \frac{n}{l} \right \rfloor =\left \lfloor \frac{n}{r} \right \rfloor =k\)

所以根据它的性质可以推到:\(\frac{n}{r}\ge k\), 移项得:\(\frac{n}{k} \ge r\),即:$r \le \frac{n}{k} $.那么 $r_{max}=\left \lfloor \frac{n}{k} \right \rfloor $

所以将 $k=\left \lfloor \frac{n}{l} \right \rfloor $ 代入得: $r_{max}=\left \lfloor \frac{n}{\left \lfloor \frac{n}{l} \right \rfloor } \right \rfloor $

所以这就是整除分块了。

至于时间复杂度,可以这么证:
因为在 $i\le \sqrt{n} $ 时,\(i\) 最多有 \(\sqrt{n}\) 种取值,所以 $\left \lfloor \frac{n}{i} \right \rfloor $ 也最多只有 \(\sqrt{n}\) 种取值。

在 \(n \ge i\ge \sqrt{n}\) 时,故易证: $\left \lfloor \frac{n}{i} \right \rfloor $ 也最多只有 \(\sqrt{n}\) 种取值。

在 \(i\ge n\) 时,只有1和0这两种取值,省略。

所以时间复杂度为 \(O(\sqrt{n})\) 的。

CODE

#include<bits/stdc++.h>
#define int long long
#define ri register int
#define N 200005
#define mod 998244353
#define wk(x) write(x),putchar(' ')
#define wh(x) write(x),putchar('\n')

using namespace std;
int n,m,k,jk,ans,sum,num,cnt,tot;
int head[N],dis[N],vis[N],wis[N],f[N];

void read(int &x){
	x=0;int ff=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if(ch=='-') ff=-1;ch=getchar();}
	while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
	x*=ff;return;
}

void write(int x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10+'0');return;
}

signed main()
{
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	read(n);
	for(int i=1,r=1;i<=n;i=r+1) r=(n/(n/i)),(ans+=(n/r)*(r-i+1)%mod)%=mod;//可以不模
	wh(ans);
	return 0;
}
/*
read(n);
for(int i=1;i<=n;i++) ans+=n/i;//暴力
wh(ans);
*/
posted @ 2026-07-08 10:27  Red_river_hzh  阅读(13)  评论(0)    收藏  举报