莫比乌斯函数
定义
(mu) 表示莫比乌斯函数,是一个由容斥系数所构成的函数, (mu{(d)}) 的定义是:
1.当d等于1时, (mu{(d)} = 1)
2.当d由k个不同的质因子组成时,(mu{(d)} = (-1)^k) (注:一定是互不相同的质因子
3.其它情况(mu{(d)} = 0)
性质
1.对于任意正整数n,都有(sumlimits_{d|n}mu{(d)} = [n = 1])
即当n等于1时 原式等于1,其它情况下 ,原式等于0
首先当n等于1时 ,显然答案是1
当n不等于1时,答案与那些(mu)值是0的项肯定没有关系
现在考虑n有k个互不相同的质因子 它们分别组合
假定i个质因子相互组合 此时的方案数有(inom{k}{i})种
而此时的(mu)值为((-1)^k)
所以对于一个非1的n 最终的求和式子也就是
((-1)^1*inom{k}{1}+(-1)^2*inom{k}{2}+...+(-1)^k*inom{k}{k}+1)(最后的1是(mu{(1)}) 因为通过质因子相乘是无法组合出1的,所以要把漏掉的情况补上)
而1又等于((-1)^0*inom{k}{0})
所以原式就变成了((-1)^0*inom{k}{0}+(-1)^1*inom{k}{1}+(-1)^2*inom{k}{2}+...+(-1)^k*inom{k}{k})
没有感到这个式子很熟悉?
不熟悉去找数学老师跪搓衣板
二项式定理:((a-b)^k = inom{k}{0}a^k*b^0+inom{k}{1}a^{k-1}*b^1+...+inom{k}{k}a^0*b^k)
所以原式就等于((1-1)^k) 即0
(由第一条性质知当且仅当(gcd(i,j)=1)时后面的和式有值,所以成立
将d提前
后面的枚举空循环显然是没有意义的
所以化为
然后两边同除(n) 得到
原式得证
另一种证明:
由狄利克雷卷积(varphi = id*mu)
得到(varphi(n)=sum_{d|n}mu(d)cdot frac{n}{d})
两边同时处理n 得到原式
筛法比筛一般的积性函数还要简单一点
void sieve(){
mu[1] = 1;
for(int i = 2;i <= maxk - 5;++i) {
if(!vis[i]) prime[++cnt] = i,mu[i] = -1;
for(int j = 1;j <= cnt && prime[j] * i <= maxk - 5;++j) {
vis[prime[j]*i] = 1;
mu[i*prime[j]] = -mu[i];
if(i % prime[j] == 0) {mu[i*prime[j]] = 0;break;}
}
}
}
莫比乌斯反演
前提:(f())是积性函数
证明:
关于最后一步:
首先由性质1知 当(d != n) 时 答案为0
所以只需要统计当(d = n)时的答案
所以最后得到(f(n))
另一种形式:
题
A:P2257 YY的GCD
题目求(gcd(i,j) epsilon prime)的个数
写成柿子
一般套路,(gcd(i,j) = 1) 可以化成(sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} sumlimits_{d|gcd(i,j)}mu{(d)})
原因很显然
由莫比乌斯函数性质一:(sumlimits_{d|n}mu{(d)} = [n = 1])
把(gcd(i,j))代入n就好了
而该题要求的是gcd为素数的
所以想到可以枚举素数 然后套式子
假设此时的gcd(i,j) = k
则答案变为(sumlimits_{k=1}^{n} sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} gcd(i,j)=k)
此时k一定满足(k|i,k|j)
也就是(sumlimits_{k=1}^{n} sumlimits_{i=1}^{left lfloor frac{n}{k} ight floor} sumlimits_{j=1}^{left lfloor frac{m}{k} ight floor} sumlimits_{d|gcd(i,j)}mu{(d)})
发现可以把d提前 然后就变成了(sumlimits_{k=1}^{n} sumlimits_{d=1}^{left lfloor frac{n}{k} ight floor} sumlimits_{i=1}^{left lfloor frac{n}{k*d} ight floor} sumlimits_{j=1}^{left lfloor frac{m}{k*d} ight floor} mu{(d)})
此时i和j这两维显然就没用了 因为后面的(mu{(d)})与i,j无关
直接去掉 把加法改成乘法就好了
(sumlimits_{k=1}^{n} sumlimits_{d=1}^{left lfloor frac{n}{k} ight floor}left lfloor frac{n}{k*d} ight floor*left lfloor frac{m}{k*d} ight floor*mu{(d)})
然后我们的60分就到手了
现在考虑优化这个式子
设T = k*d
那么有原式等于(sumlimits_{k=1}^{n} sumlimits_{d=1}^{left lfloor frac{n}{k} ight floor}left lfloor frac{n}{T} ight floor*left lfloor frac{m}{T} ight floor*mu{(d)})
发现此时的T可以提前
所以原式就变为了(sumlimits_{T=1}^{n} left lfloor frac{n}{T} ight floor*left lfloor frac{m}{T} ight floor sumlimits_{k|T,k epsilon prime}mu{(frac{T}{k})})
发现(sumlimits_{k|T,k epsilon prime}mu{(frac{T}{k})}) 是可以预处理的
只要计算一个(mu{(d)})时,把它所有倍数T 都加上一个对应的贡献(mu{(frac{T}{d})})就可以了
计算前缀和 方便整除分块的时候快速计算贡献
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e7 + 10;
int prime[maxn];
int vis[maxn];
int mu[maxn];
int cnt;
int f[maxn];
ll sum[maxn];
void init(){
mu[1] = 1;
for(int i = 2;i <= maxn - 5;++i) {
if(!vis[i]) vis[i] = 1,prime[++cnt] = i,mu[i] = -1;
for(int j = 1;j <= cnt && prime[j] * i <= maxn - 5;++j) {
vis[i*prime[j]] = 1;
if(i % prime[j] == 0) break;
mu[i*prime[j]] = -mu[i];
}
}
for(int i = 1;i <= cnt;++i)
for(int j = 1;j <= maxn && prime[i] * j <= maxn - 5;++j)
f[j*prime[i]] += mu[j];
for(int i = 1;i <= maxn - 5;++i) sum[i] = sum[i-1] + f[i];
}
int main(){
init();
int T;scanf("%d",&T);
while(T--) {
int n,m; scanf("%d%d",&n,&m); if(n > m) swap(n,m);
ll ans = 0;
for(int l = 1,r;l <= n;l = r + 1) {
r = min(n/(n/l),m/(m/l));
ans += (sum[r] - sum[l-1]) * (n / l) * (m / l);
}
printf("%lld
",ans);
}
return 0;
}
B: P3327 约数个数和
(sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} d(ij))
难点显然在于如何转化(d(ij))
(d(ij))可以化成(sumlimits_{x|i}^{i} sumlimits_{y|j}^{j} [gcd(x,y)=1]) 的形式
考虑(ij)的每个因子 对于每个每个因子一定可以划分成({p_1}^{c1}*{p_2}^{c2}*...)
规定每个指数首先从i中选 i中不够再从j中选 这样每个因子一定可以找到唯一的一种划分 而每一种划分一定可以对应唯一的因子
而对于(sumlimits_{x|i}^{i} sumlimits_{y|j}^{j} [gcd(x,y)=1])
首先(x*y)一定是(i*j)的因子
(gcd(x,y) = 1) 说明x与y不含有相同的质因子
考虑划分规则 对于(x=1,y=2)和(x=2,y=1) 此时构造出来的因子并不相同 因为y有值的条件是 x已经选完
所以(y=2)时表示 构造出一个(i)中所有的质因子2都选 (j)中选了一个 而(y=1)时显然不同 所以不会重复
而因为每一个因子都可以用这样的方法构造出来 所以不会漏掉情况
然后就是一般的莫比乌斯反演了
将式子代入可得(sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} sumlimits_{x|i} sumlimits_{y|j} [gcd(x,y)=1])
将(x,y)提前 得到
(sumlimits_{x=1}^{n} sumlimits_{y=1}^{m} sumlimits_{i|x} sumlimits_{j|y} [gcd(i,j)=1])
显然后面的枚举可以省掉 得到
(sumlimits_{x=1}^{n} sumlimits_{y=1}^{m} left lfloor n/x
ight
floor left lfloor m / y
ight
floor [gcd(i,j)=1])
设(f(x) = sumlimits_{x=1}^{n} sumlimits_{y=1}^{m} left lfloor n/x ight floor left lfloor m / y ight floor [gcd(i,j)=x])
(g(x) = sumlimits_{x|d} f(d))
(g(x) = sumlimits_{x|d} sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} left lfloor n/i ight floor left lfloor m / j ight floor [gcd(i,j)=d])
发现第一维的枚举可以省掉 变为
(g(x) = sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} left lfloor n/i ight floor left lfloor m / j ight floor [x|gcd(i,j)])
将gcd消除 得
(g(x) = sumlimits_{i=1}^{frac{n}{x}} sumlimits_{j=1}^{frac{m}{x}} left lfloor n/ix
ight
floor left lfloor m/jx
ight
floor)
然后移项得到
(g(x) = sumlimits_{i=1}^{frac{n}{x}} left lfloor n / ix
ight
floor sumlimits_{j=1}^{frac{m}{x}} left lfloor m/jx
ight
floor)
预处理出(f(x) = sumlimits_{i=1}^{x}left lfloor x/i ight floor)
然后就可以O(1)计算g函数了
又有(f(x) = sumlimits_{x|d} mu(d/x) g(d))
则(f(1) = sumlimits_{i=1}^{n} mu(i) g(i))
(f(1) = sumlimits_{x=1}^{n} mu(x)sumlimits_{i=1}^{frac{n}{x}} left lfloor n / ix ight floor sumlimits_{j=1}^{frac{m}{x}} left lfloor m/jx ight floor)
后面的部分可以整除分块优化成根号
C:P4449 于神之怒加强版
(假定(n <= m))
首先原式可以化为
(sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} sumlimits_{d=1}^{n} [gcd(i,j)=d] * d^k)
移项 得
(sumlimits_{d=1}^{n} d^k sumlimits_{i=1}^{n} sumlimits_{j=1}^{m} [gcd(i,j)=d])
即
(sumlimits_{d=1}^{n} d^k sumlimits_{i=1}^{left lfloor frac{n}{d}
ight
floor}sumlimits_{j=1}^{left lfloor frac{m}{d}
ight
floor}[gcd(i,j)=1])
一般套路将gcd消除得到
(sumlimits_{d=1}^{n} d^k sumlimits_{i=1}^{left lfloor frac{n}{d} ight floor}sumlimits_{j=1}^{left lfloor frac{m}{d} ight floor}sumlimits_{k|gcd(i,j)} mu(k))
将k提前 得
(sumlimits_{d=1}^{n} d^k sumlimits_{k=1}^{left lfloor frac{n}{d} ight floor} sumlimits_{i=1}^{left lfloor frac{n}{dk} ight floor}sumlimits_{j=1}^{left lfloor frac{m}{dk} ight floor} mu(k))
发现后面的式子跟(i,j)没有关系 ,即
(sumlimits_{d=1}^{n} d^k sumlimits_{k=1}^{left lfloor frac{n}{d} ight floor} left lfloor frac{n}{dk} ight floor left lfloor frac{m}{dk} ight floor mu(k))
令(T=dk)
有
(sumlimits_{d=1}^{n}d^k sumlimits_{k=1}^{left lfloor frac{n}{d} ight floor} left lfloor frac{n}{T} ight floor left lfloor frac{m}{T} ight floor mu(k))
将枚举d改为枚举T 有
(sumlimits_{T=1}^{n} left lfloor frac{n}{T} ight floor left lfloor frac{m}{T} ight floor sumlimits_{d|T}mu(frac{T}{k}) * d^k)
发现后面的部分可以预处理
令(g(x) = sumlimits_{d|x}mu(frac{x}{k}) * d^k)
则(g(x))为积性函数
所以可以线性筛把(g())函数筛出来
一个质数(p)的函数值可以算出 等于(p^k-1)
考虑(g[i*prime[j]]) 如果(i)与(prime[j])互质 显然可以直接乘起来 得到函数值
如果(i) % (prime[j] != 0)时 考虑如何快速求出函数值
发现(i)一定可以表示为({p_1}^{c_1}*{p_2}^{c2}*...)
乘(prime[j])后一定是 ({p_1}^{c_1+1} * {p_2}^{c2} * ...)
后面的部分完全一样
所以考虑如何计算前面的部分
因为(g[i*prime[j]] = g[i] / g[{p_1}^{c1}] * g[{p_1}^{c1+1}])
对于后面的部分 等于
(sumlimits_{d|{p_1}^{c_1+1}}mu(frac{{p_1}^{c_1+1}}{d}) * d^k)
由(mu)函数定义可知 只有当(d)取({p_1}^{c_1+1}) 或者 ({p_1}^{c_1}) 时 (mu)值不为0
得到(g[{p_1}^{c1+1}] = {{p_1}^{(c_1+1)}}^k - {{p_1}^{c_1}}^k = {{p_1}^{c_1}}^k *( {p_1}^{k} - 1))
而(g[{p_1}^{c1}] = {{p_1}^{c_1}}^k - {{p_1}^{(c_1-1)}}^k = {{p_1}^{(c_1-1)}}^k *( {p_1}^{k} - 1))
所以(g[{p_1}^{c1+1}] = g[{p_1}^{c1}] * {p_1}^k)
所以就可以线性筛了
筛完之后 处理一下前缀和 然后整除分块就可以了
D:jzptab
很套路的题
(sum_{i=1}^{n}sum_{j=1}^{m}lcm(i,j))
(sum_{i=1}^{n}sum_{j=1}^{m}frac{ij}{gcd(i,j)})
枚举gcd
(sum_{d=1}^{n}frac{1}{d}sum_{i=1}^{n}sum_{j=1}^{m} ij*[(i,j)=d])
(sum_{d=1}^{n}frac{1}{d}sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}} ij*d^2*[(i,j)=1])
发现(d^2)可以提前 得到
(sum_{d=1}^{n} dsum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}} ij*[(i,j)=1])
把([(i,j)=1]) 展开
(sum_{d=1}^{n} dsum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}} ij sum_{k|gcd(i,j)} mu(k))
交换枚举顺序
(sum_{d=1}^{n} d sum_{k=1}^{frac{n}{d}}mu(k) sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}} ij*k^2)
(k^2) 提前得到
(sum_{d=1}^{n} d sum_{k=1}^{frac{n}{d}}k^2mu(k) sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}} ij)
Solution1:
到这里已经可以过掉洛谷的数据了 单组询问,时限2s
(sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}} ij) 就是两个等差数列乘起来
所以可以用整除分块做到根号复杂度
发现对于n来说,(sum_{k=1}^{frac{n}{d}}k^2mu(k)) 也可以整除分块处理
所以两个整除分块处理 O(n)预处理 O((n^frac{3}{4}))回答每次询问
Solution2:
但是另一个数据范围是时限8s,1e4组询问
上面的式子可以继续化简
设(T = dk)
(sum_{T=1}^{n} sum_{k|T} k^2mu(k)*frac{T}{k}sum_{i=1}^{frac{n}{T}} sum_{j=1}^{frac{m}{T}}ij)
中间的部分可以(nln)预处理 后面的部分可以整除分块
一个小trick是当(mu(i)=0)时直接跳过,可以减小一半常数
然后就可以做到(O(nln))预处理 (O(sqrt{n}))处理单组询问
Solution3:
但是我们可以做到更优秀的时间复杂度
复杂度瓶颈显然在预处理 考虑怎么优化这个过程
发现可以把原式再化一下变成
(sum_{T=1}^{n} Tsum_{k|T} k*mu(k)sum_{i=1}^{frac{n}{T}} sum_{j=1}^{frac{m}{T}}ij)
令(F[n] = sum_{k|n} k * mu(k))
然后发现中间的式子就是个积性函数
关于为什么是积性函数 两个积性函数对位相乘显然是积性函数
而(id) 跟 (mu) 都是积性函数 所以这东西也是积性函数
然后就可以线性筛了
只需要考虑特殊情况:
p为质数 (F[p] = 1 - p)
(p^k) 考虑原式,只有当因子等于(1)或p时(mu)值不为0
所以(F[p^k] = 1-p)
(low[i]) 表示i的(p_1^{c1}) 即i最小质因子的贡献
所以(F[i*prime[j]] = F[i/low[i]] * F[low[i]*prime[j]])
(low[i]*prime[j]) 一定是(p^k) 的形式
所以(F[i*prime[j]] = F[i/low[i]] *F[low[i]] = F[i])
所以就可以线性筛了
Solution4:
还是考虑优化预处理的部分
发现中间的式子完全就是狄利克雷前缀和的模板 然后就可以做了
E: 数表
需要一点点小转化 之前没有见过这种套路记录一下
首先不考虑a的限制
令(f[i])表示i的约数和
列出式子
求 $sum_{i=1}^{n} sum_{j=1}^{m} f[gcd(i,j)] $
简单化一下有
(sum_{d=1}^{n} sum_{i=1}^{n} sum_{j=1}^{m} f[d] * [gcd(i,j)=d])
很显然的式子了 推过好多遍的 直接到终态
(sum_{T=1}^{n}sum_{d|T}f(d)mu(frac{T}{d}) left lfloor frac{n}{T} ight floorleft lfloor frac{m}{T} ight floor)
如果没有a的限制我们到这里就做完了
考虑有a的限制怎么办
a的限制是对于(f(d))的
所以可以对于(f(d))按照权值排序
对于询问按照a排序
每次暴力加入一些新的(f(d)) 并更新前缀和
然后整除分块回答询问
更新前缀和可以套一个树状数组 就很方便了
一共会更新(nln)次答案,每次更新答案复杂度为(log) 所以修改总复杂度为(nln*log)
每次回答询问是(O(sqrt{n}))
F:数字表格
挺新的套路
(prod_{i=1}^{n} prod_{j=1}^{m}f[gcd(i,j)])
这个题不同的地方在于变成了乘法,先化式子
(prod_{d=1}^{n}prod_{i=1}^{n} prod_{j=1}^{m} f[d]^{[gcd(i,j)=d]})
连乘可以放到指数上去 所以
(prod_{d=1}^{n}f[d]^{sum_{i=1}^{n}sum_{j=1}^{m}[gcd(i,j)=d]})
一般套路
(prod_{d=1}^{n}f[d]^{sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}}[gcd(i,j)=1]})
(prod_{d=1}^{n}f[d]^{sum_{i=1}^{frac{n}{d}}sum_{j=1}^{frac{m}{d}}sum_{k|gcd(i,j)}mu(k)})
(prod_{d=1}^{n}f[d]^{sum_{k=1}^{frac{n}{d}} mu(k) sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}}})
然后把k放到外边
(prod_{d=1}^{n}prod_{k=1}^{frac{n}{d}}f[d]^{ mu(k) sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}}})
令T=dk
改为枚举T, 原式变为
(prod_{T=1}^{n}prod_{d|T} f(d)^{mu(frac{T}{d})frac{n}{T}frac{m}{T}})
原式等于(prod_{T=1}^{n}(prod_{d|T} f(d)^{mu(frac{T}{d})})^{frac{n}{T}frac{m}{T}})
外面的部分显然可以整除分块 , 里面的部分直接暴力就可以了
G:DZY Loves Math
求 (sum_{i=1}^{n}sum_{j=1}^{m}f(gcd(i,j)))
(sum_{d=1}^{n}f(d)sum_{k=1}^{frac{n}{d}}mu(k)sum_{i=1}^{frac{n}{dk}}sum_{j=1}^{frac{m}{dk}}) (中间的步骤都是套路就直接跳过了)
令T=dk
(sum_{T=1}^{n} sum_{d|T}f(d)mu(frac{T}{d})frac{n}{dk}frac{m}{dk})
显然重点在于把中间的部分处理掉
令(g(T) = sum_{d|T}f(d)mu(frac{T}{d}))
考虑怎么求这个函数
首先我们要求的一定是(mu)值不为0的项
将T分解为(p_1^{a_1}*p_2^{a_2}*...*p_k^{a_k})
将d分解后
我们选择的(cnt_i)一定满足(a_i-1 <= cnt_i <= a_i) 这样的项才会对答案造成贡献
而考虑存在(i,j)其中(a_i<a_j) 那么此时这个(g(T))一定为0
因为选或者不选i ,对于答案是没有影响的((f)函数的定义)
而选i与不选i时的(mu)值是恰好互为相反数的,所以这样的项对答案的贡献为0
而当所有(a_i = a_j)时,我们可以假设此时所有的f值都等于(a_i)
那么这时候的根据刚刚的思路 可以把所有数分成两部分 一部分是选到(a_i)的 ,另一部分是选到(a_i-1)的
第二部分选到奇数个与偶数个的方案数显然是相等的 所以答案仍是0
但是当选的所有的都为(a_i-1)时,此时答案为(a_i-1) 并不是我们设的(a_i)
所以要把这个(-1)的贡献算上 , 此时贡献就是((-1)^{k+1})
然后转移就很显然了