整除(数论)分块个人小记
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);
*/
本文来自博客园,作者:Red_river_hzh,转载请注明原文链接:https://www.cnblogs.com/Red-river-hzh/p/21235080

浙公网安备 33010602011771号