【BZOJ3930】选数(莫比乌斯反演,杜教筛)
题面
给定\(n,K,L,R\)
问从\(L~R\)中选出\(n\)个数,使得他们\(gcd=K\)的方案数
题解
这样想,既然\(gcd=K\),首先就把区间缩小一下
这样变成了\(gcd=1\)
设\(f(i)\)表示\(gcd\)恰好为\(i\)的方案数
那么,要求的是\(f(1)\)
设\(g(x)=\sum_{d|x}f(d)\)
所以\(g(x)\)表示\(x|gcd\)的方案数
这个不是很好求吗?
所以一波莫比乌斯反演
\[f(1)=\sum_{i=1}\mu(i)g(i)\]
好的,看看\(g(x)\)怎么直接求
现在可以取的区间范围是\(L~R\)
要让\(gcd\)是\(x\)的倍数
区间的大小算一下,直接快速幂就行了
然后\(80\)分到手啦
#include
#include
#include
#include
#include
#include
#include
#include
现在的问题是\(L,R\)范围很大
但是我们又要求一个大的\(\mu\)
怎么办嗷。。
非线性时间诶。
杜教筛??
我们可以搞一下\(\mu\)的前缀和就行了,
这样两个相减就是\(\mu\)
设\(S(n)=\sum_{i=1}^n\mu(i)\)
\[g(1)S(n)=\sum_{i=1}^n(g*\mu)(i)-\sum_{i=2}^{n}g(i)S(\frac{n}{i})\]
取\(g(x)=1\)
\[S(n)=1-\sum_{i=2}^nS(\frac{n}{i})\]
现在可以算出\(\mu\)啦
再回去看一下上面写的代码
发现可以数论分块
于是再来一次数论分块
这题就没啦
#include
#include
#include
#include
#include
#include
#include
#include