这个是学习莫比乌斯反演须要的预备知识,几乎全部这类的题都须要用到这个。html
考虑下面这个式子:
\[ \sum_{i=1}^{n}\lfloor\frac{n}{i}\rfloor \]
这个固然能够\(O(n)\)算,可是不少时候这样还不够快,因而下面有一个\(O(\sqrt{n})\)的算法。算法
经过打表能够发现,当\(i\)为连续一段时,后面那玩意都是同样的。函数
而后对于\(i\),最后一个和它相同的位置是\(n/(n/i)\),注意这里都是整除,而后共有\(O(\sqrt{n})\)个块,因此咱们就能够每次跳一个块,快速算出结果,代码以下:学习
int n;read(n); int ans=0,T=1; while(T<=n) { int pre=T;T=n/(n/T); ans=ans+(T-pre+1)*(n/T);T++; } write(ans);
关于莫比乌斯函数,其实并非一个很玄学的东西,它本质上就是一个容斥系数。spa
对于莫比乌斯函数,它写做\(\mu(d)\),定义以下:code
而后对于这个函数有一个最为重要的性质:
\[ \sum_{d|n}\mu(d)=[n=1] \]
证实其实很简单,将\(n\)进行惟一分解,获得\(n=\prod_{i=1}^ka_i^{p_i}\)只须要考虑容斥,对于\(n\)的每个因数只能选或不选,则:
\[ \sum_{d|n}\mu(d)=\sum_{i=0}^{k}(-1)^i\binom{k}{i}=[k=0] \]
而后\([k=0]\)其实等价于\([n=1]\),得证。htm
线筛也很简单,根据定义就能够了,代码:blog
void sieve() { mu[1]=1; for(int i=2;i<maxn;i++) { if(!vis[i]) pri[++tot]=i,mu[i]=-1; for(int t,j=1;j<=tot&&i*pri[j]<maxn;j++) { vis[t=i*pri[j]]=1; if(!(i%pri[j])) {mu[t]=0;break;} mu[t]=-mu[i]; } } }
前置知识讲完了,其实真的很水。get
定义\(f(n)\)和\(g(n)\),已知:
\[ f(n)=\sum_{d|n}g(d) \]
而后已知\(f\),求\(g\)。it
其实这个和推容斥差不太多,因为我想把前面的莫比乌斯函数的性质用上,因此先说一句废话:
\[ g(n)=\sum_{d|n}[\frac{n}{d}=1]g(d) \]
而后发现这个东西和上面长的很像,带进去:
\[ \begin{align} g(n)&=\sum_{d|n}\sum_{i|\frac{n}{d}}\mu(i)g(d)\\ &=\sum_{d|n}g(d)\sum_{i|\frac{n}{d}}\mu(i) \end{align} \]
而后先枚举\(i\):
\[ \begin{align} g(n)&=\sum_{i|n}\mu(i)\sum_{d|\frac{n}{i}}g(d) \end{align} \]
而后后面那个式子其实就是\(f\),因此:
\[ g(n)=\sum_{d|n}\mu(d)f(\frac{n}{d}) \]
而后就作完了。
这个东西就是莫比乌斯反演:
已知
\[ f(n)=\sum_{d|n}g(d) \]
那么能够获得:
\[ g(n)=\sum_{d|n}\mu(d)f(\frac{n}{d}) \]
其实作题的话,直接把\(\sum_{d|n}\mu(d)=[n=1]\)带到题目给的式子里更好推一些。
最主要的仍是多作题,作多了就会发现其实都是一个套路,还有就是式子要本身拿纸笔来推,这点很重要。
(题目难度基本按顺序排列,推荐按顺序写)