【洛谷4917】天守阁的地板(莫比乌斯反演)
- 给定\(n\),求\(\prod_{i=1}^n\prod_{j=1}^n\frac{ij}{gcd(i,j)^2}\)。
- 数据组数\(\le10^3,n\le10^6\)
一道很水的反演题,然而日常智障地推错了一步,结果卡了半天。不过最后还是完全靠自己推出来的。
由于好久没做过莫比乌斯反演的题目了,这篇博客就写得详细一些吧。
第一阶段
套路地枚举\(gcd\),但要注意由于这道题中是\(\prod\)而不是\(\sum\),\([gcd(i,j)=1]\)要放在指数上:
根据\(\sum_{d|n}\mu(d)=[n=1]\)这一莫比乌斯反演基本性质,转化得到:
根据指数运算法则\(x^{a+b}=x^a\cdot x^b\),可以把指数中的\(\sum\)移下来变成\(\prod\):
调整枚举顺序,把\(p\)放到\(i,j\)前面:
而\(\prod_{i=1}^{\lfloor\frac n{dp}\rfloor}\prod_{j=1}^{\lfloor\frac n{dp}\rfloor}(ip\cdot jp)\)这一项其实就等于\((\lfloor\frac n{dp}\rfloor!\cdot p^{\lfloor\frac n{dp}\rfloor})^{2\lfloor\frac n{dp}\rfloor}\),于是得到:
第二阶段
套路地令\(D=dp\),然后改为枚举\(D,p\),得到:
由于题目中的\(n\)是每次给定的,所以我们需要尽可能将含\(n\)的项单独抠出,因此得到:
先看\(\prod_{p|D}(\lfloor\frac nD\rfloor!)^{2\mu(p)\lfloor\frac n{D}\rfloor}\)这一项,我们重新把\(p\)移回指数,得到:
也就是说,这一项只有在\(D=1\)时值才不为\(1\),且此时值为\((n!)^{2n}\)。
然后考虑令\(f(D)=\prod_{p|D}p^{2\mu(p)}\),这个可以\(O(nlogn)\)预处理。
那么原式就被化简成了:
此时只要再对于每次询问除法分块一下就可以了。
代码:\(O(nlogn+T\sqrt nlogn)\)
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 1000000
#define X 19260817
using namespace std;
int n,f[N+5],g[N+5],Fac[N+5],Pt,P[N+5],mu[N+5];
I int QP(RI x,RI y) {RI t=1;W(y) y&1&&(t=1LL*t*x%X),x=1LL*x*x%X,y>>=1;return t;}
I void Sieve()//线性筛预处理μ
{
RI i,j;for(mu[1]=1,i=2;i<=N;++i)
for(!P[i]&&(mu[P[++Pt]=i]=X-2),j=1;j<=Pt&&i*P[j]<=N;++j)
if(P[i*P[j]]=1,i%P[j]) mu[i*P[j]]=X-1-mu[i];else break;
}
int main()
{
RI Tt,i,j,t;for(Sieve(),Fac[0]=i=1;i<=N;++i) Fac[i]=1LL*Fac[i-1]*i%X,f[i]=1;//预处理阶乘,并给f数组赋初值1
for(i=1;i<=N;++i) for(t=1LL*QP(i,2*mu[i]%(X-1)),j=i;j<=N;j+=i) f[j]=1LL*f[j]*t%X;//预处理f
for(f[0]=g[0]=i=1;i<=N;++i) f[i]=1LL*f[i-1]*f[i]%X,g[i]=QP(f[i],X-2);//预处理f的前缀积及其逆元
RI l,r;scanf("%d",&Tt);W(Tt--)//处理询问
{
for(scanf("%d",&n),t=QP(Fac[n],n<<1),l=1;l<=n;l=r+1)//除法分块
r=n/(n/l),t=1LL*t*QP(1LL*f[r]*g[l-1]%X,1LL*(n/l)*(n/l)%(X-1))%X;
printf("%d\n",t);
}return 0;
}