洛谷 P5518 - [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题(莫比乌斯反演+整除分块)
一道究极恶心的毒瘤六合一题,式子推了我满满两面 A4 纸……
首先我们可以将式子拆成:
\]
也就是说我们需要算出以下四项式子的值:
\]
\]
\]
\]
显然前两项与后两项是等价的,因此我们只需算出:
\]
与
\]
即可求出答案。
考虑对 \(type\) 进行分类讨论,首先是 \(type=0\),那么
\]
考虑每个 \(i\) 的贡献,稍微想想即可得到:
\]
然后是 \(f_2(0)\),套路地枚举 \(\gcd(i,j)\) 有
f_2(0)&=\prod\limits_{i=1}^A\prod\limits_{j=1}^B\prod\limits_{k=1}^C\gcd(i,j)\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{i=1}^A\sum\limits_{j=1}^B[\gcd(i,j)=d]})^C\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{i=1}^{A/d}\sum\limits_{j=1}^{B/d}[\gcd(i,j)=1]})^C\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{p}\mu(p)\lfloor\frac{A}{dp}\rfloor\lfloor\frac{B}{dp}\rfloor})^C\\
\end{aligned}
\]
最右边那个 \(k\) 次方显然可以忽略掉不管它,最后求个快速幂即可。考虑对里面的 \(dp\) 进行二维的整除分块,那么答案的式子可以化为:
f_2(0)=(\prod\limits_{dp}g_1(dp)^{\lfloor\frac{A}{dp}\rfloor\lfloor\frac{B}{dp}\rfloor})^C
\end{aligned}
\]
其中
\]
考虑整除分块,对于一段区间 \([L,R]\),满足 \(\forall x\in[L,R]\) 均有 \(\lfloor\dfrac{A}{x}\rfloor=\lfloor\dfrac{A}{L}\rfloor,\lfloor\dfrac{B}{x}\rfloor=\lfloor\dfrac{B}{L}\rfloor\),我们这样计算它们的贡献:
\]
预处理前缀积即可 \(\mathcal O(1)\) 计算,时间复杂度 \(\mathcal O(\log n\sqrt{n})\)。
接下来是 \(type=1\) 的情况,个人感觉与 \(type=0\) 的情况大差不差,毕竟指数上都只与 \(i,j,k\) 本身而不涉及到它们的 \(\gcd\) 之类,只不过指数上枚举变量的次数稍微高了一点点,导致情况较于 \(type=0\) 略有一点点繁琐。
首先是 \(f_1(1)\)
\]
还是考虑每个 \(i\) 的贡献被累计了多少次:
f_1(0)&=(A!)^{\sum\limits_{j=1}^B\sum\limits_{k=1}^Cjk}\\
&=(A!)^{\frac{B(B+1)}{2}·\frac{C(C+1)}{2}}
\end{aligned}
\]
一波快速幂带走。
其次是 \(f_2(1)\)
f_2(1)&=\prod\limits_{i=1}^A\prod\limits_{j=1}^B\prod\limits_{k=1}^C\gcd(i,j)^{ijk}\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{i=1}^A\sum\limits_{j=1}^Bij[\gcd(i,j)=d]})^{\sum\limits_{k=1}^Ck}\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{i=1}^{A/d}\sum\limits_{j=1}^{B/d}ijd^2[\gcd(i,j)=1]})^{\frac{C(C+1)}{2}}\\
&=(\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{p}\mu(p)d^2p^2·s(\lfloor\frac{A}{dp}\rfloor)s(\lfloor\frac{B}{dp}\rfloor)})^{\frac{C(C+1)}{2}}\\
\end{aligned}
\]
其中 \(s(i)=\dfrac{i(i+1)}{2}\)
那么我们还是枚举 \(dp\),按照 \(f_2(0)\) 的套路设一个 \(g_2(x)\),定义如下:
\]
那么考虑对 \(dp\) 进行整除分块,那么
\]
预处理 \(g_2(dp)\) 的前缀积然后对 \(dp\) 整除分块即可。
最后是 \(type=2\) 的情况
先考虑 \(f_1(2)\)
\]
上来先把 \(\gcd\) 反演掉:
f_1(2)&=\prod\limits_{d=1}^{\min(A,B,C)}\prod\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}(id)^{d·\sum\limits_{j=1}^{\lfloor\frac{B}{d}\rfloor}\sum\limits_{k=1}^{\lfloor\frac{C}{d}\rfloor}[\gcd(i,j,k)=1]}\\
&=\prod\limits_{d=1}^{\min(A,B,C)}\prod\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}(id)^{d·\sum\limits_{p\mid i}\mu(p)\lfloor\frac{B}{dp}\rfloor\lfloor\frac{C}{dp}\rfloor}
\end{aligned}
\]
把 \(p\) 提到外面来
f_1(2)&=\prod\limits_{d=1}^{\min(A,B,C)}\prod\limits_{p}(\prod\limits_{i\in[1,\lfloor\frac{A}{d}\rfloor]\&p\mid i}(id)^{d·\mu(p)})^{\lfloor\frac{B}{dp}\rfloor\lfloor\frac{C}{dp}\rfloor}
\end{aligned}
\]
然后按照套路枚举 \(\dfrac{i}{p}\)
f_1(2)&=\prod\limits_{d=1}^{\min(A,B,C)}\prod\limits_{p}(\prod\limits_{i=1}^{\lfloor\frac{A}{dp}\rfloor}(idp)^{d·\mu(p)})^{\lfloor\frac{B}{dp}\rfloor\lfloor\frac{C}{dp}\rfloor}
\end{aligned}
\]
然后枚举 \(dp\),根据 \(\mu*i=\varphi\) 可知 \(\sum\limits_{d·p=x}d·\mu(p)=\varphi(x)\),于是
\]
外面的东西显然整除分块一下就好了,里面的东西
\]
显然等于
&\prod\limits_{i=1}^{\lfloor\frac{A}{x}\rfloor}i^{\varphi(x)}·x^{\varphi(x)}\\
=&((\lfloor\dfrac{A}{x}\rfloor)!)^{\varphi(x)}·(x^{\varphi(x)})^{\lfloor\frac{A}{x}\rfloor}
\end{aligned}
\]
然后套路地预处理 \(g_3=x^{\varphi(x)}\) 的前缀积,以及 \(\varphi(x)\) 的前缀和即可在整除分块的过程中 \(\mathcal O(1)\) 求出式子的值,注意 \(\varphi(x)\) 的前缀和应 \(\bmod(MOD-1)\) 而不是 \(\bmod MOD\),因为 \(\varphi(x)\) 的前缀和作用在指数上。
时间复杂度 \(\sqrt{n}\log n\)
然后是最精神污染的一个式子:
\]
按照 P1587 的套路,碰到两个 \(\gcd\) 咱们最好不要莽,要一个个反演,因此考虑先反演下面这个 \(\gcd\):
f_2(2)&=\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{i=1}^{\lfloor\frac{A}{d}\rfloor}\sum\limits_{j=1}^{\lfloor\frac{B}{d}\rfloor}[\gcd(i,j)=1]\sum\limits_{k=1}^C\gcd(d,k)}\\
&=\prod\limits_{d=1}^{\min(A,B)}d^{\sum\limits_{p}^{\lfloor\frac{\min(A,B)}{d}\rfloor}\mu(p)\lfloor\frac{A}{dp}\rfloor\lfloor\frac{B}{dp}\rfloor\sum\limits_{k=1}^C\gcd(d,k)}
\end{aligned}
\]
发现后面有个 \(\sum\limits_{k=1}^C\gcd(d,k)\),考虑对这个东西单独推个式子:
g_4(d,C)&=\sum\limits_{k=1}^C\gcd(d,k)\\
&=\sum\limits_{x\mid d}x·\sum\limits_{i=1}^{\lfloor\frac{C}{x}\rfloor}[i\perp\dfrac{d}{x}]\\
&=\sum\limits_{x\mid d}x·\sum\limits_{y\mid\frac{d}{x}}\mu(y)\lfloor\dfrac{C}{xy}\rfloor
\end{aligned}
\]
套路地枚举 \(xy=T\) 可得:
\]
这已经是本题中第二次看到这个式子了:
\]
于是
\]
带回去
\]
按照这里总结出来的套路,看到先枚举 \(i\) 再枚举 \(j\mid i\) 的求和/积式我们可以考虑交换求和/积的顺序,先枚举 \(j\) 再枚举 \(i\),这样会出现下取整,就可以整除分块了。
因此考虑先枚举 \(T\) 再枚举 \(d\),有:
\]
然后考虑拆开来:
\]
先考虑前面的式子:
\]
考虑枚举 \(dp=x\),那么:
\text{原式}&=(T^{\varphi(T)\lfloor\frac{C}{T}\rfloor})^{\sum\limits_{x}\sum\limits_{p\mid x}\mu(p)\lfloor\frac{A}{Tx}\rfloor\lfloor\frac{B}{Tx}\rfloor}\\
&=(T^{\varphi(T)\lfloor\frac{C}{T}\rfloor})^{\epsilon(x)\lfloor\frac{A}{Tx}\rfloor\lfloor\frac{B}{Tx}\rfloor}\\
&=(T^{\varphi(T)\lfloor\frac{C}{T}\rfloor})^{\lfloor\frac{A}{T}\rfloor\lfloor\frac{B}{T}\rfloor}
\end{aligned}
\]
对 \(T\) 整除分块一下,预处理 \(\varphi(T)\) 的前缀和即可 \(\mathcal O(1)\) 算出。
然后是后面的式子(胜利就在眼前!)
\]
还是对 \(T\) 整除分块,然后枚举 \(dp=x\),那么上面的式子可以写成:
\]
发现最里面的括号的东西就是在求 \(f_2(0)\) 时用到的 \(g_1(x)\),那么我们再套一个对 \(x\) 的整除分块即可。
根据整除分块里再套一个整除分块复杂度是 \(\sum\limits_{x,\exists k,s.t.\lfloor\frac{n}{k}\rfloor=x}\sqrt{x}=n^{0.75}\) 可知这一部分复杂度为 \(n^{0.75}\log n\)
于是这题就做完了,时间复杂度 \(n\log n+Tn^{0.75}\log n\)。
关于此题的常数问题,由于取模运算较多,可以使用快速取模优化常数,具体可见 chenxia25 神仙的这篇博客。
const int MAXV=1e5;
ll mod;
int pr[MAXV/5+5],prcnt=0,vis[MAXV+5],mu[MAXV+5],smu[MAXV+5],phi[MAXV+5];
int fac[MAXV+5],prd[MAXV+5],prd_inv[MAXV+5],prd_sq[MAXV+5],prd_sq_inv[MAXV+5];
int pre_ii[MAXV+5],inv_pre_ii[MAXV+5],pre_mul[MAXV+5],inv_pre_mul[MAXV+5];
int inv[MAXV+5],prd_phi[MAXV+5],prd_phi_inv[MAXV+5];
int sphi[MAXV+5];
__int128_t _base1=1,_base2=1;
inline int mol1(__int128_t x){return x-mod*(_base1*x>>64);}
inline int mol2(__int128_t x){return x-(mod-1)*(_base2*x>>64);}
int qpow(int x,int e){
if(e<0) e+=mod-1;int ret=1;
for(;e;e>>=1,x=mol1(1ll*x*x)) if(e&1) ret=mol1(1ll*ret*x);
return ret;
}
int work(int x,int y){return (!y)?1:((~y)?x:inv[x]);}
void sieve(int n){
for(int i=(inv[0]=inv[1]=1)+1;i<=n;i++) inv[i]=mol1(1ll*inv[mod%i]*(mod-mod/i));
mu[1]=phi[1]=1;
for(int i=(fac[0]=1);i<=n;i++) fac[i]=mol1(1ll*fac[i-1]*i);
for(int i=2;i<=n;i++){
if(!vis[i]) mu[i]=-1,pr[++prcnt]=i,phi[i]=i-1;
for(int j=1;j<=prcnt&&pr[j]*i<=n;j++){
vis[pr[j]*i]=1;
if(i%pr[j]==0){phi[i*pr[j]]=phi[i]*pr[j];break;}
mu[i*pr[j]]=-mu[i];phi[i*pr[j]]=phi[i]*phi[pr[j]];
}
}
for(int i=1;i<=n;i++) smu[i]=smu[i-1]+mu[i];
for(int i=0;i<=n;i++) prd[i]=prd_sq[i]=1;
for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i) prd[j]=mol1(1ll*prd[j]*work(i,mu[j/i]));
for(int i=1;i<=n;i++) prd[i]=mol1(1ll*prd[i-1]*prd[i]);
for(int i=0;i<=n;i++) prd_inv[i]=qpow(prd[i],-1);
for(int i=1;i<=n;i++) for(int j=i;j<=n;j+=i)
prd_sq[j]=mol1(1ll*prd_sq[j]*
qpow(qpow(i,mol2(1ll*i*i)),mol2(1ll*mu[j/i]*(j/i)*(j/i))));
for(int i=1;i<=n;i++) prd_sq[i]=mol1(1ll*prd_sq[i-1]*prd_sq[i]);
for(int i=0;i<=n;i++) prd_sq_inv[i]=qpow(prd_sq[i],-1);
pre_ii[0]=1;for(int i=1;i<=n;i++) pre_ii[i]=mol1(1ll*pre_ii[i-1]*qpow(i,i));
for(int i=0;i<=n;i++) inv_pre_ii[i]=qpow(pre_ii[i],-1);
pre_mul[0]=1;for(int i=1;i<=n;i++) pre_mul[i]=mol1(1ll*pre_mul[i-1]*work(i,mu[i]));
for(int i=0;i<=n;i++) inv_pre_mul[i]=qpow(pre_mul[i],-1);
prd_phi[0]=1;for(int i=1;i<=n;i++) prd_phi[i]=mol1(1ll*prd_phi[i-1]*qpow(i,phi[i]));
for(int i=0;i<=n;i++) prd_phi_inv[i]=qpow(prd_phi[i],-1);
for(int i=1;i<=n;i++) sphi[i]=mol2(sphi[i-1]+phi[i]);
}
int calc1(int x,int y){
int res=1;
for(int l=1,r;l<=min(x,y);l=r+1){
r=min(x/(x/l),y/(y/l));
res=1ll*res*qpow(1ll*prd[r]*prd_inv[l-1]%mod,1ll*(x/l)*(y/l)%(mod-1))%mod;
}
return res;
}
int solve1(int a,int b,int c){
int res=1ll*qpow(calc1(a,b),-c)*qpow(calc1(a,c),-b)%mod;
res=1ll*res*qpow(fac[a],1ll*b*c%(mod-1))%mod;
res=1ll*res*qpow(fac[b],1ll*a*c%(mod-1))%mod;
return res;
}
ll get(int x){return mol2(1ll*x*(x+1)/2);}
int calc2(int x,int y){
int res=1;
for(int l=1,r;l<=min(x,y);l=r+1){
r=min(x/(x/l),y/(y/l));
res=1ll*res*qpow(1ll*prd_sq[r]*prd_sq_inv[l-1]%mod,
1ll*get(x/l)*get(y/l)%(mod-1))%mod;
}
return res;
}
int solve2(int a,int b,int c){
int res=1;
res=1ll*res*qpow(pre_ii[a],(1ll*b*(b+1)>>1)%(mod-1))%mod;
res=1ll*res*qpow(pre_ii[b],(1ll*a*(a+1)>>1)%(mod-1))%mod;
res=1ll*res*qpow(calc2(a,b),mod-2)%mod;
res=qpow(res,(1ll*c*(c+1)>>1)%(mod-1));
res=1ll*res*qpow(calc2(a,c),-(1ll*b*(b+1)>>1)%(mod-1))%mod;
return res;
}
int calc3(int x,int y,int z){
int res=1;
for(int l=1,r;l<=x;l=r+1){
r=1e9;
if(x/l) chkmin(r,x/(x/l));
if(y/l) chkmin(r,y/(y/l));
if(z/l) chkmin(r,z/(z/l));
int mul=qpow(1ll*prd_phi[r]*prd_phi_inv[l-1]%mod,x/l);
mul=1ll*mul*qpow(fac[x/l],sphi[r]-sphi[l-1])%mod;
res=1ll*res*qpow(mul,1ll*(y/l)*(z/l)%(mod-1))%mod;
} return res;
}
int calc4(int x,int y,int z){
int res=1;
for(int l=1,r;l<=min(x,y);l=r+1){
r=1e9;
if(x/l) chkmin(r,x/(x/l));
if(y/l) chkmin(r,y/(y/l));
if(z/l) chkmin(r,z/(z/l));
res=1ll*res*qpow(1ll*prd_phi[r]*prd_phi_inv[l-1]%mod,1ll*(x/l)*(y/l)*(z/l)%(mod-1))%mod;
int X=x/l,Y=y/l,Z=z/l,sm=1ll*Z*(sphi[r]-sphi[l-1])%(mod-1);
for(int L=1,R;L<=min(X,Y);L=R+1){
R=1e9;
if(X/L) chkmin(R,X/(X/L));
if(Y/L) chkmin(R,Y/(Y/L));
res=1ll*res*qpow(1ll*prd[R]*prd_inv[L-1]%mod,1ll*(X/L)*(Y/L)*sm%(mod-1))%mod;
}
}
return res;
}
int solve3(int x,int y,int z){
return 1ll*calc3(x,y,z)*calc3(y,x,z)%mod*
qpow(calc4(x,y,z),-1)%mod*qpow(calc4(x,z,y),-1)%mod;
}
int main(){
int qu;scanf("%d%lld",&qu,&mod);
_base1=(_base1<<64)/mod;_base2=(_base2<<64)/(mod-1);
sieve(MAXV);
while(qu--){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
printf("%d %d %d\n",solve1(a,b,c),solve2(a,b,c),solve3(a,b,c));
}
return 0;
}
洛谷 P5518 - [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题(莫比乌斯反演+整除分块)的更多相关文章
- P5518 [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题
瞎扯 建议在阅读题解之前欣赏这首由普莉兹姆利巴姐妹带来的的合奏. Q:你参加省选吗?不是说好了考完 NOIP 就退吗. A:对啊. Q:那你学这玩意干啥? A:对啊,我学这玩意干啥? 写这题的动机? ...
- [SDOI2017]数字表格 & [MtOI2019]幽灵乐团
P3704 [SDOI2017]数字表格 首先根据题意写出答案的表达式 \[\large\prod_{i=1}^n\prod_{j=1}^mf_{\gcd(i,j)} \] 按常规套路改为枚举 \(d ...
- 题解-MtOI2019 幽灵乐团
题面 MtOI2019 幽灵乐团 给定 \(p\),\(Cnt\) 组测试数据,每次给 \(a,b,c\),求 \[\prod_{i=1}^a\prod_{j=1}^b\prod_{k=1}^c\le ...
- 【洛谷2257/BZOJ2820】YY的GCD(数论/莫比乌斯函数)
题目: 洛谷2257 预备知识:莫比乌斯定理(懵逼乌斯定理) \(\mu*1=\epsilon\)(证bu明hui略zheng) 其中(我校学长把\(\epsilon(x)\)叫单位函数但是为什么我没 ...
- 洛谷P1829 [国家集训队]Crash的数字表格 / JZPTAB(莫比乌斯反演)
题目背景 提示:原 P1829 半数集问题 已经迁移至 P1028 数的计算 题目描述 今天的数学课上,Crash小朋友学习了最小公倍数(Least Common Multiple).对于两个正整数a ...
- 洛谷 P6222 - 「P6156 简单题」加强版(莫比乌斯反演)
原版传送门 & 加强版传送门 题意: \(T\) 组数据,求 \(\sum\limits_{i=1}^n\sum\limits_{j=1}^n(i+j)^k\mu^2(\gcd(i,j))\g ...
- 洛谷 P6478 - [NOI Online #2 提高组] 游戏(二项式反演+树形 dp)
题面传送门 没错这就是我 boom0 的那场 NOIOL 的 T3 一年前,我在 NOIOL #2 的赛场上折戟沉沙,一年后,我从倒下的地方爬起. 我成功了,我不再是从前那个我了 我们首先假设 A 拥 ...
- [MtOI2019]幽灵乐团
题目 一个很暴力的辣鸡做法 考虑到两个数的\(\gcd\)是所有质数次幂取\(\min\),两个数的\(\rm lcm\)是所有质数次幂取\(\max\),于是最后的答案一定是\(\prod p_i^ ...
- 【洛谷】P1754 球迷购票问题(基础dp)
题目背景 盛况空前的足球赛即将举行.球赛门票售票处排起了球迷购票长龙. 按售票处规定,每位购票者限购一张门票,且每张票售价为50元.在排成长龙的球迷中有N个人手持面值50元的钱币,另有N个人手持面值1 ...
随机推荐
- C++编译Dlib库出现LNK2001错误(原因是在Python中安装过Dlib)
问题 使用CMake编译Dlib库,编译得到lib文件后,新建一个VS工程想使用Dlib,却出现LNK2001:无法解析的外部符号的错误,且都与JPEG和PNG相关: 1>dlib19.17.9 ...
- 微信小程序的支付流程
一.前言 微信小程序为电商类小程序,提供了非常完善.优秀.安全的支付功能 在小程序内可调用微信的API完成支付功能,方便.快捷 场景如下图所示: 用户通过分享或扫描二维码进入商户小程序,用户选择购买, ...
- Convolutional Neural Network-week1编程题(TensorFlow实现手势数字识别)
1. TensorFlow model import math import numpy as np import h5py import matplotlib.pyplot as plt impor ...
- Java:修饰符小记
Java:修饰符小记 对 Java 中的 修饰符,做一个微不足道的小小小小记 Java 语言提供了很多修饰符,大概分为两类: 访问权限修饰符 非访问权限修饰符 访问权限修饰符 修饰符 说明 publi ...
- BUAA 2020 软件工程 热身作业
BUAA 2020 软件工程 热身作业 Author: 17373051 郭骏 项目 内容 这个作业属于哪个课程 2020春季计算机学院软件工程(罗杰 任健) 这个作业的要求在哪里 第一次作业-热身! ...
- OKR与影响地图,别再傻傻分不清
摘要:OKR和影响地图虽然都是为了一个目标去进行规划的方法,但是两者侧重的内容却不一致. 本文分享自华为云社区<一分钟读懂OKR与影响地图>,作者: 敏捷的小智. 什么是OKR及影响地图 ...
- 线程池系列二:一张动图,彻底懂了execute和submit
我们知道线程池通过execute方法执行提交的Runnable任务,但Runnable只是执行任务,没有返回任何信息. [线程池原理:线程池原来是个外包公司,打工人我悟了] 若是我们想在异步执行完 ...
- tar 解压分割压缩文件
被分割后的压缩文件必须先合并成一个压缩文件才能正常的解压. 第一步.合并压缩文件 第二步.正常解压 $ls TINA-1.3.tar.gzaa TINA-1.3.tar.gzab TINA-1.3.t ...
- 禁用root直接远程登录,使用普通账号登录后再切换root
1.创建一个普通用户 #useradd test 2.给test设置密码 #passwd test 3.禁用root远程登录 #vim /etc/ssh/sshd_config #PermitRoot ...
- MongoDB 集群 config server 查询超时导致 mongos 集群写入失败
环境 OS:CentOS 7.x DB:MongoDB 3.6.12 集群模式:mongod-shard1 *3 + mongod-shard2 *3 + mongod-conf-shard *3 + ...