• 【洛谷4917】天守阁的地板(莫比乌斯反演)


    点此看题面

    • 给定(n),求(prod_{i=1}^nprod_{j=1}^nfrac{ij}{gcd(i,j)^2})
    • 数据组数(le10^3,nle10^6)

    一道很水的反演题,然而日常智障地推错了一步,结果卡了半天。不过最后还是完全靠自己推出来的。

    由于好久没做过莫比乌斯反演的题目了,这篇博客就写得详细一些吧。

    第一阶段

    套路地枚举(gcd),但要注意由于这道题中是(prod)而不是(sum)([gcd(i,j)=1])要放在指数上:

    [prod_{d=1}^nprod_{i=1}^{lfloorfrac nd floor}prod_{j=1}^{lfloorfrac nd floor}(ij)^{[gcd(i,j)=1]} ]

    根据(sum_{d|n}mu(d)=[n=1])这一莫比乌斯反演基本性质,转化得到:

    [prod_{d=1}^nprod_{i=1}^{lfloorfrac nd floor}prod_{j=1}^{lfloorfrac nd floor}(ij)^{sum_{p|gcd(i,j)}mu(p)} ]

    根据指数运算法则(x^{a+b}=x^acdot x^b),可以把指数中的(sum)移下来变成(prod)

    [prod_{d=1}^nprod_{i=1}^{lfloorfrac nd floor}prod_{j=1}^{lfloorfrac nd floor}prod_{p|gcd(i,j)}(ij)^{mu(p)} ]

    调整枚举顺序,把(p)放到(i,j)前面:

    [prod_{d=1}^nprod_{p=1}^{lfloorfrac nd floor}(prod_{i=1}^{lfloorfrac n{dp} floor}prod_{j=1}^{lfloorfrac n{dp} floor}(ipcdot jp))^{mu(p)} ]

    (prod_{i=1}^{lfloorfrac n{dp} floor}prod_{j=1}^{lfloorfrac n{dp} floor}(ipcdot jp))这一项其实就等于((lfloorfrac n{dp} floor!cdot p^{lfloorfrac n{dp} floor})^{2lfloorfrac n{dp} floor}),于是得到:

    [prod_{d=1}^nprod_{p=1}^{lfloorfrac nd floor}(lfloorfrac n{dp} floor!cdot p^{lfloorfrac n{dp} floor})^{2mu(p)lfloorfrac n{dp} floor} ]

    第二阶段

    套路地令(D=dp),然后改为枚举(D,p),得到:

    [prod_{D=1}^nprod_{p|D}(lfloorfrac nD floor!cdot p^{lfloorfrac nD floor})^{2mu(p)lfloorfrac n{D} floor} ]

    由于题目中的(n)是每次给定的,所以我们需要尽可能将含(n)的项单独抠出,因此得到:

    [prod_{D=1}^n(prod_{p|D}(lfloorfrac nD floor!)^{2mu(p)lfloorfrac n{D} floor})cdot((prod_{p|D} p^{2mu(p)})^{lfloorfrac n{D} floor^2}) ]

    先看(prod_{p|D}(lfloorfrac nD floor!)^{2mu(p)lfloorfrac n{D} floor})这一项,我们重新把(p)移回指数,得到:

    [(lfloorfrac nD floor!)^{2lfloorfrac n{D} floorsum_{p|D}mu(p)}=(lfloorfrac nD floor!)^{2lfloorfrac nD floor[D=1]} ]

    也就是说,这一项只有在(D=1)时值才不为(1),且此时值为((n!)^{2n})

    然后考虑令(f(D)=prod_{p|D}p^{2mu(p)}),这个可以(O(nlogn))预处理。

    那么原式就被化简成了:

    [(n!)^{2n}prod_{D=1}^nf(D)^{lfloorfrac nD floor^2} ]

    此时只要再对于每次询问除法分块一下就可以了。

    代码:(O(nlogn+Tsqrt 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
    ",t);
    	}return 0;
    }
    
  • 相关阅读:
    spring boot 集成kafka 添加用户认证
    Prism 开发之五 消息引擎
    Prism 开发之四 ViewModelLocator
    Prism 开发之三 模块化开发
    Prism 学习之二 事件
    Prism学习之一开始
    asp.net core 权限认证
    vue页面完成自定义标题
    在线直播网站源码开发,音视频同步的处理方案及选择
    降低游戏陪玩平台系统前端开发复杂度的方式详解
  • 原文地址:https://www.cnblogs.com/chenxiaoran666/p/Luogu4917.html
Copyright © 2020-2023  润新知