【题解】Luogu P5518 题解

Description

令:

\[f(\textit{type})=\begin{cases}1&\textit{type}=0\\ijk&\textit{type}=1\\\gcd(i,j,k)&\textit{type}=2\end{cases} \]

给定 \(A,B,C\),求:

\[\textit{ans}_{\textit{type}}=\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{\operatorname{lcm}(i,j)}{\gcd(i,k)}\right)^{f(\textit{type})} \]

多测,对给定质数 \(p\) 取模。

\(1\le A,B,C\le 10^5\)\(10^7\le p\le 1.05\times10^9,p\in\mathbb{P}\)\(T=70\)

Solution

首先对原式化简一下:

\[\begin{aligned} \textit{ans}_{\textit{type}}=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{\operatorname{lcm}(i,j)}{\gcd(i,k)}\right)^{f(\textit{type})}\\ =&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\left(\frac{ij}{\gcd(i,j)\cdot\gcd(i,k)}\right)^{f(\textit{type})} \end{aligned} \]

于是原式可以分为两个部分:

\[\begin{aligned} & \mathcal F(A,B,C) = \prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{f(\textit{type})}\\ & \mathcal G(A,B,C)=\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{f(\textit{type})} \end{aligned} \]

显然有:

\[\textit{ans}_{\textit{type}}=\frac{\mathcal F(A,B,C)\cdot\mathcal F(B,A,C)}{\mathcal G(A,B,C)\cdot\mathcal G(A,C,B)} \]

接下来就开始推柿子吧!


\(\textit{type}=0\)

\[\begin{aligned} \mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci\\ =&\prod_{i=1}^A\prod_{j=1}^Bi^C\\ =&\prod_{i=1}^Ai^{B\cdot C}\\ =&(A!)^{B\cdot C} \end{aligned} \]

预处理阶乘,每次计算快速幂即可。

\[\begin{aligned} \mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)\\ =&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)\right)^C\\ \end{aligned} \]

然后开始莫反:

\[\begin{aligned} \prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)=&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^Bd^{[\gcd(i,j)=d]}\\ =&\prod_{d=1}\prod_{i=1}^{\lfloor \frac Ad\rfloor}\prod_{j=1}^{\lfloor\frac Bd\rfloor}d^{[gcd(i,j)=1]}\\ =&\prod_{d=1}d^{\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[gcd(i,j)=1]} \end{aligned} \]

把指数提出来推一下:

\[\begin{aligned} \sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[gcd(i,j)=1]=&\sum_{e=1}\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[e\mid i][e \mid j]\mu(e)\\ =&\sum_{e=1}\sum_{i=1}^{\lfloor \frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}\mu(e)\\ =&\sum_{e=1}\lfloor \frac A{de}\rfloor\lfloor\frac B{de}\rfloor\mu(e) \end{aligned} \]

带回去就有:

\[\begin{aligned} \prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)=&\prod_{d=1}d^{\sum_{e=1}\lfloor \frac A{de}\rfloor\lfloor\frac B{de}\rfloor\mu(e)}\\ =&\prod_{t=1}\prod_{d\mid t}d^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor\mu(\frac td)}\\ =&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ \mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)\\ =&\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\right)^C\\ \end{aligned} \]

最里面括号内的东西可以用类似埃氏筛的方法预处理一下,即对于每个 \(d\),将它的贡献累乘到它的每个倍数上。预处理完成后就可以快乐的整除分块了。


\(\textit{type}=1\)

定义:\(S(n)=\sum_{i=1}^ni=\frac{n(n+1)}2\)

然后开始推柿子:

\[\begin{aligned} \mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{ijk}\\ =&\left(\prod_{i=1}^A\prod_{j=1}^Bi^{ij}\right)^{S(C)}\\ =&\left(\prod_{i=1}^Ai^i\right)^{S(B)\cdot S(C)} \end{aligned} \]

预处理 \(\prod_{i=1}^Ai^i\) 即可。

\[\begin{aligned} \mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{ijk}\\ =&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}\right)^{S(C)}\\ \prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}=&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^Bd^{[\gcd(i,j)=d]ij}\\ =&\prod_{d=1}\prod_{i=1}^{\lfloor\frac Ad\rfloor}\prod_{j=1}^{\lfloor\frac Bd\rfloor}d^{[\gcd(i,j)=1]ijd^2}\\ =&\prod_{d=1}d^{d^2\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[\gcd(i,j)=1]ij} \end{aligned} \]

把指数拎出来:

\[\begin{aligned} \sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[\gcd(i,j)=1]ij=&\sum_{e=1}\sum_{i=1}^{\lfloor\frac Ad\rfloor}\sum_{j=1}^{\lfloor\frac Bd\rfloor}[e\mid i][e\mid j]\mu(e)ij\\ =&\sum_{e=1}\sum_{i=1}^{\lfloor\frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}e^2\mu(e)ij\\ =&\sum_{e=1}e^2\mu(e)\left(\sum_{i=1}^{\lfloor\frac A{de}\rfloor}\sum_{j=1}^{\lfloor\frac B{de}\rfloor}ij\right)\\ =&\sum_{e=1}e^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor) \end{aligned} \]

带回去:

\[\begin{aligned} \prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}=&\prod_{d=1}d^{d^2\sum_{e=1}e^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor)}\\ =&\prod_{e=1}\prod_{d=1}d^{(de)^2\mu(e)S(\lfloor\frac A{de}\rfloor)S(\lfloor\frac B{de}\rfloor)}\\ =&\prod_{t=1}\prod_{d\mid t}d^{t^2\mu(\frac td)S(\lfloor\frac A{t}\rfloor)S(\lfloor\frac B{t}\rfloor)}\\ =&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{t^2S(\lfloor\frac At\rfloor)S(\lfloor\frac Bt\rfloor)}\\ \mathcal G(A,B,C)=&\left(\prod_{i=1}^A\prod_{j=1}^B\gcd(i,j)^{ij}\right)^{S(C)}\\ =&\left(\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{t^2}\right)^{S(\lfloor\frac At\rfloor)S(\lfloor\frac Bt\rfloor)}\right)^{S(C)} \end{aligned} \]

括号里的东西其实就是第一问预处理的那个东西的 \(t^2\) 次方,预处理一下即可整除分块。


\(\textit{type}=2\)

毒瘤。

\[\begin{aligned} \mathcal F(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Ci^{\gcd(i,j,k)}\\ =&\prod_{i=1}^Ai^{\sum_{j=1}^B\sum_{k=1}^C\gcd(i,j,k)}\\ =&\prod_{d=1}\prod_{i=1}^Ai^{\sum_{j=1}^B\sum_{k=1}^C[\gcd(i,j,k)=d]d}\\ =&\prod_{d=1}\prod_{i=1}^{\lfloor\frac Ad\rfloor}(id)^{\sum_{j=1}^{B/d}\sum_{k=1}^{C/d}[\gcd(i,j,k)=1]d}\\ =&\prod_{d=1}\prod_{e=1}\prod_{i=1}^{\lfloor\frac A{de}\rfloor}(ide)^{\lfloor{\frac B{de}}\rfloor\lfloor{\frac C{de}}\rfloor\mu(e)d}\\ =&\prod_{t=1}\prod_{d\mid t}\prod_{i=1}^{\lfloor\frac At\rfloor}(it)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor\mu(\frac td)d}\\ =&\prod_{t=1}\left(\prod_{d\mid t}\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\mu(\frac td)d}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\ =&\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\sum_{d\mid t}\mu(\frac td)d}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\ =&\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\cdot t^{\lfloor\frac At\rfloor}\right)^{\varphi(t)}\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\\ \end{aligned} \]

这玩意有点复杂,把它拆成两个部分:

\[\begin{aligned} & f_0(A,B,C)=\prod_{t=1}\left(\left(\lfloor\frac At\rfloor!\right)^{\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor}\right)^{\varphi(t)}\\ & f_1(A,B,C)=\prod_{t=1}\left(t^{\varphi(t)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor\lfloor\frac Ct\rfloor} \end{aligned} \]

\(f_1\) 可以整除分块了,把 \(f_2\) 先放着,看 \(\mathcal G\)

\[\begin{aligned} \mathcal G(A,B,C)=&\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^C\gcd(i,j)^{\gcd(i,j,k)}\\ =&\prod_{d=1}\prod_{i=1}^A\prod_{j=1}^B\prod_{k=1}^Cd^{[\gcd(i,j)=d]\gcd(d,k)}\\ =&\prod_{d=1}d^{\sum_{i=1}^{A/d}\sum_{j=1}^{B/d}[\gcd(i,j)=1]\sum_{k=1}^C\gcd(d,k)}\\ =&\prod_{d=1}d^{\sum_{e=1}\lfloor{\frac A{de}\rfloor}\lfloor\frac B{de}\rfloor\mu(e)\cdot\sum_{k=1}^C\gcd(d,k)}\\ =&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)\cdot\sum_{k=1}^C\gcd(d,k)}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor} \end{aligned} \]

指数上的东西:

\[\begin{aligned} \sum_{k=1}^C\gcd(d,k)=&\sum_{f\mid d}\sum_{k=1}^{\lfloor\frac Cf\rfloor}[\gcd(\frac df,k)=1]f\\ =&\sum_{f\mid d}\sum_{g\mid\frac df}\lfloor\frac C{fg}\rfloor\mu(g)f\\ =&\sum_{u\mid d}\varphi(u)\lfloor\frac Cu\rfloor \end{aligned} \]

然后带回去:

\[\begin{aligned} \mathcal G(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)\sum_{u\mid d}\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ \end{aligned} \]

这玩意不怎么好预处理。考虑把底数的 \(d\) 拆成 \(u\)\(\frac du\)

\[\begin{aligned} & g_0(A,B,C)=\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ & g_1(A,B,C)=\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor} \end{aligned} \]

分别推一下:

\[\begin{aligned} g_0(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ =&\prod_{t=1}\left(\prod_{u\mid t}\prod_{u\mid d\mid t}\left(\frac du\right)^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ =&\prod_{t=1}\left(\prod_{u\mid t}\left(\prod_{d\mid \frac tu}d^{\mu(\frac td)}\right)^{\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ =&\prod_{u=1}\left(\prod_{t=1}\left(\prod_{d\mid t}d^{\mu(\frac td)}\right)^{\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\right)^{\varphi(u)\lfloor\frac Cu\rfloor} \end{aligned} \]

括号里的东西预处理过了,两次整除分块可以搞定。

\[\begin{aligned} g_1(A,B,C)=&\prod_{t=1}\left(\prod_{d\mid t}\prod_{u\mid d}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac At\rfloor\lfloor\frac Bt\rfloor}\\ =&\prod_{u=1}\prod_{t=1}\left(\prod_{d\mid t}u^{\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor}\right)^{\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\\ =&\prod_{u=1}u^{\sum_{t=1}\sum_{d\mid t}\mu(\frac td)\varphi(u)\lfloor\frac Cu\rfloor\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor}\\ =&\prod_{u=1}u^{\varphi(u)\lfloor\frac Cu\rfloor\sum_{t=1}\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor\sum_{d\mid t}\mu(\frac td)}\\ =&\prod_{u=1}u^{\varphi(u)\lfloor\frac Cu\rfloor\sum_{t=1}\lfloor\frac A{tu}\rfloor\lfloor\frac B{tu}\rfloor[t=1]}\\ =&\prod_{u=1}u^{\varphi(u)\lfloor\frac Au\rfloor\lfloor\frac Bu\rfloor\lfloor\frac Cu\rfloor}\\ \end{aligned} \]

注意到,\(g_1\) 和之前的 \(f_1\) 其实是一样的,而且它们的值不受 \(A,B,C\) 顺序的影响,因此可以把它们约掉。


卡常小技巧(不过应该众所周知):把预处理的东西的逆元同时预处理出来可以大幅减小常数

code:

#include <cstdio>

const int N = 1e5,maxn = N + 5;

int T,p,phi,A,B,C,ta,tb,tc;
int pri[maxn],mu[maxn],Inv[maxn],f[maxn],Phi[maxn];
int fac[maxn],fd[maxn],facInv[maxn],fdInv[maxn];
int Fac[maxn],Fd[maxn],FdInv[maxn],ps[maxn];
bool isp[maxn];

inline int read() {
#define gc c = getchar()
    int d = 0,f = 0,gc;
    for(;c < 48 || c > 57;gc) f |= (c == '-');
    for(;c > 47 && c < 58;gc) d = (d << 1) + (d << 3) + (c ^ 48);
#undef gc
    return f ? -d : d;
}

inline int Mul(int a,int b,int mod) { return 1LL * a * b % mod; }
inline int Add(int a,int b,int mod) { a += b; return a > mod ? a - mod : a; }
inline int max(int a,int b) { return a > b ? a : b; }
inline int min(int a,int b) { return a < b ? a : b; }
inline int min(int a,int b,int c) { return min(min(a,b),c); }

inline int fpow(int a,int b,int mod) {
    int res = 1;
    for(;b;a = Mul(a,a,mod),b >>= 1) if(b & 1) res = Mul(res,a,mod);
    return res;
}

inline int GetInv(int a) { return a <= N ? Inv[a] : fpow(a,p - 2,p); }

namespace Type0 {
    inline int F(int A,int B,int C) { return fpow(fac[A],Mul(B,C,phi),p); }

    inline int G(int A,int B,int C) {
        int res,ans = 1;
        for(int r,l = 1;l <= A && l <= B;l = r + 1) {
            ta = A / l,tb = B / l; r = min(A / ta,B / tb);
            res = Mul(fd[r],fdInv[l - 1],p);
            ans = Mul(ans,fpow(res,Mul(ta,tb,phi),p),p);
        }
        return fpow(ans,C,p);
    }

    inline int solve() {
        int res = Mul(F(A,B,C),F(B,A,C),p);
        int inv = Mul(G(A,B,C),G(A,C,B),p);
        return Mul(res,GetInv(inv),p);
    }
}

namespace Type1 {
    inline int S(int n) { return 1LL * n * (n + 1) / 2 % phi; }

    inline int F(int A,int B,int C) { return fpow(Fac[A],Mul(S(B),S(C),phi),p); }

    inline int G(int A,int B,int C) {
        int res,ans = 1;
        for(int r,l = 1;l <= A && l <= B;l = r + 1) {
            ta = A / l,tb = B / l;
            r = min(A / ta,B / tb);
            res = Mul(Fd[r],FdInv[l - 1],p);
            ans = Mul(ans,fpow(res,Mul(S(ta),S(tb),phi),p),p);
        }
        return fpow(ans,S(C),p);
    }

    inline int solve() {
        int res = Mul(F(A,B,C),F(B,A,C),p);
        int inv = Mul(G(A,B,C),G(A,C,B),p);
        return Mul(res,GetInv(inv),p);
    }
}

namespace Type2 {
    inline int F(int A,int B,int C) { 
        int exp,res,ans = 1;
        for(int r,l = 1;l <= min(A,B,C);l = r + 1) {
            ta = A / l,tb = B / l,tc = C / l;
            r = min(A / ta,B / tb,C / tc);
            exp = Add(ps[r],phi - ps[l - 1],phi);
            res = fpow(fac[ta],Mul(tb,tc,phi),p);
            ans = Mul(ans,fpow(res,exp,p),p);
        }
        return ans;
    }

    inline int g0(int A,int B) {
        int res,ans = 1;
        for(int r,l = 1;l <= A && l <= B;l = r + 1) {
            ta = A / l,tb = B / l;
            r = min(A / ta,B / tb);
            res = Mul(fd[r],fdInv[l - 1],p);
            ans = Mul(ans,fpow(res,Mul(ta,tb,phi),p),p);
        }
        return ans;
    }

    inline int G(int A,int B,int C) {
        int res,ans = 1;
        for(int r,l = 1;l <= min(A,B,C);l = r + 1) {
            ta = A / l,tb = B / l,tc = C / l;
            r = min(A / ta,B / tb,C / tc);
            res = fpow(g0(ta,tb),tc,p);
            ans = Mul(ans,fpow(res,Add(ps[r],phi - ps[l - 1],phi),p),p);
        }
        return ans;
    }

    inline int solve() {
        int res = Mul(F(A,B,C),F(B,A,C),p);
        int inv = Mul(G(A,B,C),G(A,C,B),p);
        return Mul(res,GetInv(inv),p);
    }
}

inline void Init() {
    mu[1] = Phi[1] = f[1] = Inv[0] = Inv[1] = 1;
    fac[0] = fac[1] = Fac[0] = facInv[0] = 1;
    fd[0] = Fd[0] = fdInv[0] = FdInv[0] = 1;
    for(int i = 2;i <= N;i ++) {
        f[i] = 1,fac[i] = Mul(i,fac[i - 1],p);
        if(!isp[i]) pri[++ pri[0]] = i,mu[i] = -1,Phi[i] = i - 1;
        for(int j = 1;j <= pri[0] && i * pri[j] <= N;j ++) {
            isp[i * pri[j]] = true;
            if(!(i % pri[j])) {
                mu[i * pri[j]] = 0;
                Phi[i * pri[j]] = Phi[i] * pri[j];
                break;
            }
            mu[i * pri[j]] = -mu[i];
            Phi[i * pri[j]] = Phi[i] * Phi[pri[j]];
        }
    }
    facInv[N] = fpow(fac[N],p - 2,p);
    for(int i = N - 1;i;i --) {
        facInv[i] = Mul(facInv[i + 1],i + 1,p);
        Inv[i + 1] = Mul(facInv[i + 1],fac[i],p);
    }
    for(int i = 1;i <= N;i ++) {
        ps[i] = Add(Phi[i],ps[i - 1],phi);
        Fac[i] = Mul(Fac[i - 1],fpow(i,i,p),p);
        fd[i] = Mul(f[i],fd[i - 1],p);
        Fd[i] = Mul(fpow(f[i],Mul(i,i,phi),p),Fd[i - 1],p);
        fdInv[i] = GetInv(fd[i]),FdInv[i] = GetInv(Fd[i]);
        if(!mu[i]) continue;
        for(int j = 1;i * j <= N;j ++)
           f[i * j] = Mul(f[i * j],mu[i] == 1 ? j : Inv[j],p);
    }
}

int main() {
    T = read(),p = read();
    phi = p - 1; Init();
    for(;T;T --) {
        A = read(),B = read(),C = read();
        printf("%d %d %d\n",Type0::solve(),Type1::solve(),Type2::solve());
    }
    return 0;
}
posted @ 2022-01-15 21:56  Sya_Resory  阅读(34)  评论(0编辑  收藏  举报