• P5518 [MtOI2019]幽灵乐团 / 莫比乌斯反演基础练习题


    瞎扯

    建议在阅读题解之前欣赏这首由普莉兹姆利巴姐妹带来的的合奏。

    Q:你参加省选吗?不是说好了考完 NOIP 就退吗。
    A:对啊。
    Q:那你学这玩意干啥?
    A:对啊,我学这玩意干啥?

    写这题的动机?
    一是一直很喜欢的曲子,感觉快退役了,圆个梦。
    二是写了很多题解了,之前认为最优秀的是 NOI嘉年华的题解,但被叉掉之后不知道该怎么改了,于是删了。其他的都太不精致,都不满意。想在退役之前留下一篇最优秀的题解,于是瞅准了这题。
    再有,就是想争口气吧。

    最后扯一句,题面里将露娜萨(Lunasa)误写成了 (Lusana)。

    简述

    原题面:Luogu

    给定参数 (p),有 (T) 组数据,每次给定参数 (A,B,C),求:

    [prod_{i=1}^{A}prod_{j=1}^{B}prod_{k=1}^{C}left(dfrac{operatorname{lcm}(i,j)}{gcd(i,k)} ight)^{f(type)} ]

    其中 (f(type)) 的取值如下:

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

    (1le A,B,Cle 10^5)(10^7le ple 1.05 imes 10^9)(pin mathbb{P})(T=70)
    2.5S,128MB。

    分析

    原式

    先化下原式,原式等于:

    [prod_{i=1}^{A}prod_{j=1}^{B}prod_{k=1}^{C}left(dfrac{i imes j }{gcd(i,j) imes gcd(i,k)} ight)^{f(type)} ]

    发现每一项仅与两个变量有关,设:

    [egin{aligned} f_1(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i^{f(type)}\ f_2(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} gcd(i,j)^{f(type)} end{aligned}]

    发现 (prod) 可以随意交换,则原式等价于:

    [dfrac{f_1(a,b,c) imes f_1(b,a,c)}{f_2(a,b,c) imes f_2(a,c,b)} ]

    考虑在 (type) 取值不同时,如何快速求得 (f_1)(f_2)
    一共有 (6) 个需要推导的式子,不妨就叫它们 (1sim 6) 面了(


    type = 0

    [egin{aligned} f_1(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i\ f_2(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} gcd(i,j) end{aligned}]

    对于 1 面,显然有:

    [prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i = left(prod_{i=1}^{a}i ight)^{b imes c} ]

    预处理阶乘 + 快速幂即可,单次计算时间复杂度 (O(log n))


    再考虑 2 面,套路地枚举 (gcd),显然有:

    [large egin{aligned} &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) ight)^c\ =& left(prod_{d=1} d^{left(sumlimits_{i=1}^{a}sumlimits_{j=1}^{b}[gcd(i,j) = d] ight)} ight)^c end{aligned}]

    指数是个套路,可以看这里:P3455 [POI2007]ZAP-Queries。于是有:

    [egin{aligned} &sumlimits_{i=1}^{a}sumlimits_{j=1}^{b}[gcd(i,j) = d]\ =& sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}[gcd(i,j) = 1]\ =& sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}sum_{kmid gcd(i,j)}mu (k)\ =& sum_{k=1}mu(k)leftlfloordfrac{a}{kd} ight floorleftlfloordfrac{b}{kd} ight floor end{aligned}]

    代回原式,略做处理,则原式等于:

    [large egin{aligned} &left(prod_{d=1} d^{left(sumlimits_{k=1}mu(k)leftlfloorfrac{a}{kd} ight floorleftlfloorfrac{b}{kd} ight floor ight)} ight)^c\ =& left(prod_{d=1} left(d^{sumlimits_{k=1}mu(k)} ight)^{leftlfloorfrac{a}{kd} ight floorleftlfloorfrac{b}{kd} ight floor} ight)^c\ =& prod_{d=1} left(prod_{k=1}^{leftlfloorfrac{n}{d} ight floor}d^{left(mu(k)leftlfloorfrac{a}{kd} ight floorleftlfloorfrac{b}{kd} ight floor ight)} ight)^c end{aligned}]

    「SDOI2017」数字表格 一样,考虑枚举 (t=kd)(d),则原式等于:

    [large prod_{t=1}^{n}left(left(prod_{d|t} d^{mu{left(frac{t}{d} ight)}} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor} ight)^c ]

    设:

    [large g_0(t) = prod_{d|t}d^{muleft(frac{t}{d} ight)} ]

    线性筛预处理 (mu) 后,(g_0(t)) 可以用埃氏筛预处理,时间复杂度 (O(nlog n))。再代回原式,原式等于:

    [large prod_{t=1}^{a}left(g_0(t)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor} ight)^c ]

    预处理 (g_0(t)) 的前缀积和前缀积的逆元,复杂度 (O(nlog n))
    数论分块 + 快速幂计算即可,单次时间复杂度 (O(sqrt nlog n))


    type = 1

    [egin{aligned} f_1(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i^{i imes j imes k}\ f_2(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} gcd(i,j)^{i imes j imes k} end{aligned}]

    考虑 3 面,把 (prod k) 扔到指数位置,有:

    [large prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i^{i imes j imes k} = prod_{i=1}^{a}prod_{j=1}^{b}i^{left(i imes j imes sumlimits_{k = 1}^{c} k ight)} ]

    再把 (prod j) 也扔到指数位置,引入 (operatorname{sum}(n) = sum_{i=1}^{n} i = frac{n(n+1)}{2}),原式等于:

    [left(prod_{i=1}^{a}i^i ight)^{operatorname{sum}(b) imes operatorname{sum}(c)} ]

    预处理 (i^i) 的前缀积,复杂度 (O(nlog n))
    指数可以 (O(1)) 算出,然后快速幂,单次时间复杂度 (O(log n))

    根据费马小定理,指数需要对 (p - 1) 取模。注意 (p-1) 不是质数,计算 (operatorname{sum}) 时不能用逆元,但乘不爆 LL,直接算就行。


    再考虑 4 面,发现 (k)(gcd) 无关,则同样把 (prod k) 扔到指数位置,则有:

    [large egin{aligned} &prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} gcd(i,j)^{i imes j imes k}\ =& left(prod_{i=1}^aprod_{j=1}^bgcd(i,j)^{i imes j} ight)^{operatorname{sum}(c)} end{aligned}]

    套路地枚举 (gcd),原式等于:

    [large left(prod_{d=1}d^{left(sumlimits_{i=1}^a sumlimits_{j=1}^b i imes j[gcd(i,j)=d] ight)} ight)^{operatorname{sum}(c)} ]

    大力化简指数,有:

    [large egin{aligned} &sumlimits_{i=1}^a sumlimits_{j=1}^b i imes j[gcd(i,j)=d]\ =& d^2 sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor} sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor} i imes j[gcd(i,j)=1\ =& d^2 sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor} i sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor} jsumlimits_{t|gcd(i,j)}mu(t)\ =& d^2 sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor} i sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor} jsumlimits_{k|gcd(i,j)}mu(k)\ =& d^2 sumlimits_{k=1}mu(k)sumlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor} i[k|i] sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor} j[k|j]\ =& d^2 sumlimits_{k=1}k^2mu(k)sumlimits_{i=1}^{leftlfloorfrac{a}{kd} ight floor} isumlimits_{j=1}^{leftlfloorfrac{b}{kd} ight floor} j\ =& d^2sumlimits_{k=1}k^2mu(k)operatorname{sum}{left(leftlfloorfrac{a}{kd} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{kd} ight floor ight)}\ end{aligned}]

    指数化不动了,代回原式,原式等于:

    [large left(prod_{d=1}d^{left(d^2sumlimits_{k=1}k^2mu(k)operatorname{sum}{left(leftlfloorfrac{a}{kd} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{kd} ight floor ight)} ight)} ight)^{operatorname{sum}(c)} ]

    同 2 面的情况,先展开一下,再枚举 (t=kd)(d),原式等于:

    [large egin{aligned} &left(prod_{d=1}left(prod_{k=1}^{leftlfloorfrac{n}{d} ight floor}d^{left(d^2 k^2mu(k) ight)} ight)^{left(operatorname{sum}{left(leftlfloorfrac{a}{kd} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{kd} ight floor ight)} ight)} ight)^{operatorname{sum}(c)}\ =& prod_{t=1}left(left(prod_{d|t}d^{left(d^2left(frac{t}{d} ight)^2muleft(frac{t}{d} ight) ight)} ight)^{operatorname{sum}{left(leftlfloorfrac{a}{t} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{t} ight floor ight)}} ight)^{operatorname{sum}(c)}\ =& prod_{t=1}left(left(prod_{d|t}d^{left(t^2muleft(frac{t}{d} ight) ight)} ight)^{operatorname{sum}{left(leftlfloorfrac{a}{t} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{t} ight floor ight)}} ight)^{operatorname{sum}(c)} end{aligned}]

    与二面相同,设:

    [large g_1(t) = prod_{d|t}d^{left(t^2muleft(frac{t}{d} ight) ight)} ]

    (g_1(t)) 可以用埃氏筛套快速幂筛出,时间复杂度 (O(nlog^2 n))。再代回原式,原式等于:

    [prod_{t=1}left(g_1(t)^{operatorname{sum}{left(leftlfloorfrac{a}{t} ight floor ight)} operatorname{sum}{left(leftlfloorfrac{b}{t} ight floor ight)}} ight)^{operatorname{sum}(c)} ]

    同样预处理 (g_1(t)) 的前缀积及其逆元,时间复杂度 (O(nlog n))
    整除分块 + 快速幂即可,单次时间复杂度 (O(sqrt nlog n))

    注意指数的取模。


    type = 2

    [egin{aligned} f_1(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i^{gcd(i,j,k)}\ f_2(a,b,c) &= prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} gcd(i,j)^{gcd(i,j,k)} end{aligned}]

    考虑 5 面,手段同上,大力反演化简一波,再调换枚举对象,则有:

    [large egin{aligned} &prod_{i=1}^{a}prod_{j=1}^{b}prod_{k=1}^{c} i^{gcd(i,j,k)}\ =&prod_{d=1}prodlimits_{i=1}^{a}i^{left(sumlimits_{j=1}^{b}sumlimits_{k=1}^{c}[gcd(i,j,k)=d] ight)}\ =& prod_{d=1}prodlimits_{i=1}^{a}i^{left(sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}sumlimits_{k=1}^{leftlfloorfrac{c}{d} ight floor}[gcd(frac{i}{d},j,k)=1] ight)}\ =& prod_{d=1}prodlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}(id)^{left(dsumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}sumlimits_{k=1}^{leftlfloorfrac{c}{d} ight floor}[gcd(i,j,k)=1] ight)}\ =& prod_{d=1}prodlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}(id)^{left(dsumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}sumlimits_{k=1}^{leftlfloorfrac{c}{d} ight floor}sumlimits_{x|gcd(i,j,k)}{mu(x)} ight)}\ =& prod_{d=1}prodlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}(id)^{left(dsumlimits_{x=1}mu(x)[x|i]sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}[x|j]sumlimits_{k=1}^{leftlfloorfrac{c}{d} ight floor}[x|k] ight)}\ =& prod_{d=1}prod_{x=1}prodlimits_{i=1}^{leftlfloorfrac{a}{d} ight floor}(id)^{left(d imes mu(x)[x|i]sumlimits_{j=1}^{leftlfloorfrac{b}{d} ight floor}[x|j]sumlimits_{k=1}^{leftlfloorfrac{c}{d} ight floor}[x|k] ight)}\ =& prod_{d=1}prod_{x=1}prodlimits_{i=1}^{leftlfloorfrac{a}{xd} ight floor}(ixd)^{left(d imes mu(x){leftlfloorfrac{b}{xd} ight floor}{leftlfloorfrac{c}{xd} ight floor} ight)}\ =& prod_{t = 1}prod_{d|T}prod_{i=1}^{leftlfloorfrac{a}{t} ight floor}(it)^{left(d imes muleft(frac{t}{d} ight){leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor} ight)}\ =& prod_{t = 1}prod_{d|T}left(t^{leftlfloorfrac{a}{t} ight floor}prod_{i=1}^{leftlfloorfrac{a}{t} ight floor}i ight)^{d imes muleft(frac{t}{d} ight){leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}}\ end{aligned}]

    引入 (operatorname{fac}(n) = prod_{i=1}^{n} i),再根据枚举对象调整一下指数,原式等于:

    [large egin{aligned} &prod_{t = 1}prod_{d|t}left(t^{leftlfloorfrac{a}{t} ight floor} imes operatorname{fac}left(leftlfloorfrac{a}{t} ight floor ight) ight)^{left(d imes muleft(frac{t}{d} ight){leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor} ight)}\ =& prod_{t = 1}left(prod_{d|t}left(t^{leftlfloorfrac{a}{t} ight floor} imes operatorname{fac}left(leftlfloorfrac{a}{t} ight floor ight) ight)^{d imes muleft(frac{t}{d} ight)} ight)^{{leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}}\ =& prod_{t = 1}left(left(t^{leftlfloorfrac{a}{t} ight floor} imes operatorname{fac}left(leftlfloorfrac{a}{t} ight floor ight) ight)^{sumlimits_{d|t}d imes muleft(frac{t}{d} ight)} ight)^{{leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}} end{aligned}]

    指数中出现了一个经典的狄利克雷卷积的形式,对其进行反演。
    ((operatorname{Id}ast mu) (n)= varphi (n)) 代入原式,原式等于:

    [large egin{aligned} &prod_{t = 1}left(t^{leftlfloorfrac{a}{t} ight floor} imes operatorname{fac}left(leftlfloorfrac{a}{t} ight floor ight) ight)^{varphi(t){leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}}\ =& prod_{t = 1}left(t^{varphi(t)leftlfloorfrac{a}{t} ight floor{leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}} imes operatorname{fac}left(leftlfloorfrac{a}{t} ight floor ight)^{varphi(t){leftlfloorfrac{b}{t} ight floor}{leftlfloorfrac{c}{t} ight floor}} ight) end{aligned}]

    预处理 (t^{varphi(t)}) 的前缀积及逆元,阶乘的前缀积及阶乘逆元,(pmod {p-1}) 下的 (varphi(t)) 的前缀和(指数
    ),时间复杂度 (O(nlog n))
    同样整除分块 + 快速幂即可,单次时间复杂度 (O(sqrt nlog n))


    然后是最掉 sans 的 6 面。有 (gcd(i,j,k) = gcd(gcd(i,j), k)),考虑先枚举 (gcd(i,j)),然后套路化式子,则有:

    [large egin{aligned} &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}^{c} [gcd(i,j)=d] d^{gcd(d,k)}\ =& prod_{d=1} left(d^{left(sumlimits_{i=1}^{a}sumlimits_{j=1}^{b} [gcd(i,j)=d] ight)} ight)^{sumlimits_{k=1}^{c}gcd(d,k)} end{aligned}]

    先考虑最外面的指数,这也是个套路,可以参考 一个例子。用 (operatorname{Id} = varphi ast 1) 反演,显然有:

    [large egin{aligned} &sumlimits_{k=1}^{c}gcd(d,k)\ =& sumlimits_{k=1}^{c}sum_{x|gcd(d,k)}varphi(x)\ =& sum_{x=1}varphi(x)[x|d]sum_{k=1}^{c}[x|k]\ =& sum_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor end{aligned}]

    再考虑里面的指数,发现这式子在 2 面已经推了一遍了,于是直接拿过来用,有:

    [sumlimits_{i=1}^{a}sumlimits_{j=1}^{b}[gcd(i,j) = d]=sum_{y=1}mu(y)leftlfloordfrac{a}{yd} ight floorleftlfloordfrac{b}{yd} ight floor ]

    将化简后的两个指数代入原式,原式等于:

    [large egin{aligned} &prod_{d=1} left(d^{left(sumlimits_{y=1}mu(y)leftlfloorfrac{a}{yd} ight floorleftlfloorfrac{b}{yd} ight floor ight)} ight)^{sumlimits_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor}\ =& prod_{d=1} left(prodlimits_{y=1}d^{left(mu(y)leftlfloorfrac{a}{yd} ight floorleftlfloorfrac{b}{yd} ight floor ight)} ight)^{sumlimits_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor} end{aligned}]

    与 2、4 面同样套路地,考虑枚举 (t=yd)(d),再略作调整,原式等于:

    [large egin{aligned} &prod_{d=1} left(prodlimits_{y=1}d^{left(mu(y)leftlfloorfrac{a}{yd} ight floorleftlfloorfrac{b}{yd} ight floor ight)} ight)^{sumlimits_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor}\ =& prod_{t=1}prod_{d|t} d^{left(muleft(frac{t}{d} ight)leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floorsumlimits_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor ight)}\ =& prod_{t=1}left(prod_{d|t} d^{left(muleft(frac{t}{d} ight)sumlimits_{x|d}varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor}\ =& prod_{t=1}left(prod_{d|t} prod_{x|d}d^{left(muleft(frac{t}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor} end{aligned}]

    发现要同时枚举 (d)(x),化不动了。
    从题解里学到一个比较神的技巧,考虑把 (d) 拆成 (x)(frac{d}{x}) 分别计算贡献再相乘,即分别计算下两式:

    [large egin{aligned} &prod_{t=1}left(prod_{d|t} prod_{x|d}x^{left(muleft(frac{t}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor}\ &prod_{t=1}left(prod_{d|t} prod_{x|d}{left(frac{d}{x} ight)}^{left(muleft(frac{t}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor} end{aligned}]


    先考虑 (x) 的情况,首先把枚举 (x) 调整到最外层。设 (operatorname{lim}=max(a,b,c)),则原式等于:

    [large egin{aligned} &prod_{x=1} prod_{t=1}^{operatorname{lim}}[x|t]left(prod_{d|t} [x|d]{x}^{left(muleft(frac{t}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor}\ =& prod_{x=1} prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}left(prod_{d|t} {x}^{left(muleft(frac{tx}{dx} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor}\ =& prod_{x=1} prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}prod_{d|t} {x}^{left(varphi(x)leftlfloorfrac{c}{x} ight floorleftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floormuleft(frac{t}{d} ight) ight)} end{aligned}]

    (prod {t}) 挪到指数位置,原式等于:

    [large egin{aligned} &prod_{x=1} {x}^{left(sumlimits_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}sumlimits_{d|t}varphi(x)leftlfloorfrac{c}{x} ight floorleftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floormuleft(frac{t}{d} ight) ight)}\ =& prod_{x=1} {x}^{left(varphi(x)leftlfloorfrac{c}{x} ight floorsumlimits_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floorsumlimits_{d|t}muleft(frac{t}{d} ight) ight)} end{aligned}]

    指数中又出现了一个经典的狄利克雷卷积的形式,对其进行反演。
    ((mu ast 1) (n)= epsilon (n)=[n=1]) 代入原式,原式等于:

    [large egin{aligned} &prod_{x=1} {x}^{left(varphi(x)leftlfloorfrac{c}{x} ight floorsumlimits_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor[t=1] ight)}\ =& prod_{x=1} {x}^{left(varphi(x)leftlfloorfrac{a}{x} ight floorleftlfloorfrac{b}{x} ight floorleftlfloorfrac{c}{x} ight floor ight)} end{aligned}]

    得到了一个非常优美的式子,而且发现这个式子是 5 面最终答案的一部分。同 5 面的做法,直接整除分块即可。


    再考虑 (frac{d}{x}) 的情况,同上先把枚举 (x) 放到最外层,并调整一下指数,则原式等于:

    [large egin{aligned} &prod_{x=1} prod_{t=1}^{operatorname{lim}}[x|t]left(prod_{d|t} [x|d]{left(frac{d}{x} ight)}^{left(muleft(frac{t}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{t} ight floorleftlfloorfrac{b}{t} ight floor}\ =& prod_{x=1} prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}left(prod_{d|tx} [x|d]{left(frac{d}{x} ight)}^{left(muleft(frac{tx}{d} ight)varphi(x)leftlfloorfrac{c}{x} ight floor ight)} ight)^{leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor}\ =& prod_{x=1} left(prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}left(prod_{d|tx} [x|d]{left(frac{d}{x} ight)}^{muleft(frac{tx}{d} ight)} ight)^{leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor} ight)^{varphi(x)leftlfloorfrac{c}{x} ight floor} end{aligned}]

    考虑枚举 (dx),替换原来的 (d),注意一下这里的倍数关系。原式等于:

    [large prod_{x=1} left(prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}left(prod_{d|t}d^{muleft(frac{t}{d} ight)} ight)^{leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor} ight)^{varphi(x)leftlfloorfrac{c}{x} ight floor} ]

    发现最内层的式子 (prod_{d|t}d^{muleft(frac{t}{d} ight)}),即为二面处理过的 (g_0(t))。直接代入,原式等于:

    [large prod_{x=1} left(prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}g_0(t)^{leftlfloorfrac{a}{tx} ight floorleftlfloorfrac{b}{tx} ight floor} ight)^{varphi(x)leftlfloorfrac{c}{x} ight floor} ]

    一个小结论,证明可以看 这里

    [forall a,b,cin mathbb{Z},leftlfloordfrac{a}{bc} ight floor = leftlfloor{dfrac{leftlfloordfrac{a}{b} ight floor}{c}} ight floor ]

    则原式等于:

    [large prod_{x=1} left(prod_{t=1}^{leftlfloorfrac{operatorname{lim}}{x} ight floor}g_0(t)^{leftlfloorfrac{leftlfloorfrac{a}{x} ight floor}{t} ight floorleftlfloorfrac{leftlfloorfrac{b}{x} ight floor}{t} ight floor} ight)^{varphi(x)leftlfloorfrac{c}{x} ight floor} ]

    于是可以先对外层整除分块,再对内层整除分块。

    然后就做完了,哈哈哈。

    实现

    一些实现上的小技巧:

    • 逆元能预处理就预处理。
    • 注意对指数取模,模数为 (p-1)
    //知识点:莫比乌斯反演 
    /*
    By:Luckyblock
    用了比较清晰易懂的变量名,阅读体验应该会比较好。  
    vsc 的自动补全真是太好啦!
    */
    #include <algorithm>
    #include <cctype>
    #include <cstdio>
    #include <cstring>
    using std::min;
    using std::max;
    #define LL long long
    const int Lim = 1e5;
    const int kN = 1e5 + 10;
    //=============================================================
    LL A, B, C, mod, ans;
    int T, p_num, p[kN];
    bool vis[kN];
    LL mu[kN], phi[kN], fac[kN], g[2][kN];
    LL sumphi[kN], prodt_phi[kN], prodi_i[kN], prodg[2][kN];
    LL inv[kN], inv_fac[kN], inv_prodt_phi[kN], inv_prodg[2][kN];
    //=============================================================
    inline int read() {
      int f = 1, w = 0;
      char ch = getchar();
      for (; !isdigit(ch); ch = getchar())
        if (ch == '-') f = -1;
      for (; isdigit(ch); ch = getchar()) {
        w = (w << 3) + (w << 1) + (ch ^ '0');
      }
      return f * w;
    }
    void Chkmax(int &fir_, int sec_) {
      if (sec_ > fir_) fir_ = sec_;
    }
    void Chkmin(int &fir_, int sec_) {
      if (sec_ < fir_) fir_ = sec_;
    }
    LL QPow(LL x_, LL y_) {
      x_ %= mod;
      y_ %= mod - 1;
      LL ret = 1;
      for (; y_; y_ >>= 1ll) {
        if (y_ & 1) ret = ret * x_ % mod;
        x_ = x_ * x_ % mod;
      }
      return ret;
    }
    LL Inv(LL x_) {
      return QPow(x_, mod - 2);
    }
    LL Sum(LL n_) {
      return ((n_ * (n_ + 1ll)) / 2ll) % (mod - 1);
    }
    void Euler() {
      vis[1] = true, mu[1] = phi[1] = 1; //初值
      for (int i = 2; i <= Lim; ++ i) {
        if (! vis[i]) {
          p[++ p_num] = i;
          mu[i] = -1;
          phi[i] = i - 1;
        }
        for (int j = 1; j <= p_num && i * p[j] <= Lim; ++ j) {
          vis[i * p[j]] = true;
          if (i % p[j] == 0) {
            mu[i * p[j]] = 0;
            phi[i * p[j]] = phi[i] * p[j];
            break;
          }
          mu[i * p[j]] = -mu[i];
          phi[i * p[j]] = phi[i] * (p[j] - 1);
        }
      }
    }
    void Prepare() {
      Euler();
      inv[1] = fac[0] = prodt_phi[0] = prodi_i[0] = 1;
      for (int i = 1; i <= Lim; ++ i) {
        g[0][i] = g[1][i] = 1;
        fac[i] = 1ll * fac[i - 1] * i % mod;
        sumphi[i] = (sumphi[i - 1] + phi[i]) % (mod - 1);
        prodi_i[i] = prodi_i[i - 1] * QPow(i, i) % mod;
        if (i > 1) inv[i] = (mod - mod / i) * inv[mod % i] % mod;
    
        prodt_phi[i] = prodt_phi[i - 1] * QPow(i, phi[i]) % mod;
        inv_prodt_phi[i] = Inv(prodt_phi[i]);
      }
    
      for (int d = 1; d <= Lim; ++ d) {
        for (int j = 1; d * j <= Lim; ++ j) {
          int t = d * j;
          if (mu[j] == 1) {
            g[0][t] = g[0][t] * d % mod;
            g[1][t] = g[1][t] * QPow(1ll * d, 1ll * t * t) % mod;
          } else if (mu[j] == -1) {
            g[0][t] = g[0][t] * inv[d] % mod;
            g[1][t] = g[1][t] * Inv(QPow(1ll * d, 1ll * t * t)) % mod;
          }
        }
      }
      inv_prodg[0][0] = prodg[0][0] = 1;
      inv_prodg[1][0] = prodg[1][0] = 1;
      inv_prodt_phi[0] = 1;
      for (int i = 1; i <= Lim; ++ i) {
        for (int j = 0; j <= 1; ++ j) {
          prodg[j][i] = prodg[j][i - 1] * g[j][i] % mod;
          inv_prodg[j][i] = Inv(prodg[j][i]);
        }
      }
    }
    LL f1(LL a_, LL b_, LL c_, int type) {
      if (! type) return QPow(fac[a_], b_ * c_);
      if (type == 1) return QPow(prodi_i[a_], Sum(b_) * Sum(c_));
      LL ret = 1, lim = min(min(a_, b_), c_);
      for (LL l = 1, r = 1; l <= lim; l = r + 1) {
        r = min(min(a_ / (a_ / l), b_ / (b_ / l)), c_ / (c_ / l));
        ret = ret * QPow(prodt_phi[r] * inv_prodt_phi[l - 1], (a_ / l) * (b_ / l) % (mod - 1) * (c_ / l)) % mod;
        ret = ret * QPow(fac[a_ / l], (sumphi[r] - sumphi[l - 1] + mod - 1) % (mod - 1) * (b_ / l) % (mod - 1) * (c_ / l)) % mod;
      }
      return ret;
    }
    LL f2_2(LL a_, LL b_) { 
      LL ret = 1;
      for (LL l = 1, r = 1; l <= min(a_, b_); l = r + 1) {
        r = min(a_ / (a_ / l), b_ / (b_ / l));
        ret = ret * QPow(prodg[0][r] * inv_prodg[0][l - 1], 1ll * (a_ / l) * (b_ / l)) % mod;
      }
      return ret;
    }
    LL f2(LL a_, LL b_, LL c_, int type) {
      LL ret = 1;
      if (! type) {
        for (LL l = 1, r = 1; l <= min(a_, b_); l = r + 1) {
          r = min(a_ / (a_ / l), b_ / (b_ / l));
          LL val = QPow(prodg[0][r] * inv_prodg[0][l - 1], 1ll * (a_ / l) * (b_ / l));
          ret = (ret * QPow(val, c_)) % mod;
        }
      } else if (type == 1) {
        for (LL l = 1, r = 1; l <= min(a_, b_); l = r + 1) {
          r = min(a_ / (a_ / l), b_ / (b_ / l));
          LL val = QPow(prodg[1][r] * inv_prodg[1][l - 1], Sum(a_ / l) * Sum(b_ / l));
          ret = (ret * QPow(val, Sum(c_))) % mod;
        }
      } else {
        LL lim = min(min(a_, b_), c_);
        for (LL l = 1, r = 1; l <= lim; l = r + 1) {
          r = min(min(a_ / (a_ / l), b_ / (b_ / l)), c_ / (c_ / l));
          ret = ret * QPow(f2_2(a_ / l, b_ / l), (sumphi[r] - sumphi[l - 1] + mod - 1) % (mod - 1) * (c_ / l)) % mod;
          ret = ret * QPow(prodt_phi[r] * inv_prodt_phi[l - 1], (a_ / l) * (b_ / l) % (mod - 1) * (c_ / l)) % mod;
        }
      }
      return ret;
    }
    //=============================================================
    int main() {
      T = read(), mod = read();
      Prepare();
      while (T -- ) {
        A = read(), B = read(), C = read();
        for (int i = 0; i <= 2; ++ i) {
          ans = f1(A, B, C, i) * f1(B, A, C, i) % mod;
          ans = ans * Inv(f2(A, B, C, i)) % mod * Inv(f2(A, C, B, i)) % mod;
          printf("%lld ", ans);  
        }
        printf("
    ");
      }
      return 0;
    }
    
  • 相关阅读:
    游标
    mobaxterm安装与使用(root_35/37/36/121)
    美团笔试--修改矩阵
    美团笔试1--螺旋矩阵
    assert函数
    2019年头条笔试--围坐分糖果
    邻值查找——stl函数lower_bound和upper_bound的使用
    动态规划练习1--腾讯暑期实习正式批
    Windows 7下硬盘安装CentOS6.4的解决方法
    Sublime Text 3 的一些基本使用方法和配置
  • 原文地址:https://www.cnblogs.com/luckyblock/p/13975070.html
Copyright © 2020-2023  润新知