瞎扯
建议在阅读题解之前欣赏这首由普莉兹姆利巴姐妹带来的的合奏。
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;
}