前言
\(\color{black}{{\rm C}}\color{red}{{\rm YJian}}\) 出的大毒瘤题,集 \(3\) 和 \(1\) ,卡常,还有数学几大令人上吐下泻的毒瘤于一体,充分考察了选手的耐心,所以说静下心来还是非常有思考价值的。
注意本题大量运用了莫反的套路,所以推荐先做几道莫反的题练练手。
这是我做这题胡写的推导(你要实在不想看这篇题解看看这个也不失为上上策)
Description
\(T\) 次询问,每次给定 \(a\) , \(b\) , \(c\) ,求下列三个式子的值:
-
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \frac{\text{lcm}(i, j)}{\gcd(i, k)}
\]
-
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \Big(\frac{\text{lcm}(i, j)}{\gcd(i, k)}\Big) ^ {i \cdot j \cdot k}
\]
-
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \Big(\frac{\text{lcm}(i, j)}{\gcd(i, k)}\Big) ^ {\gcd(i, j, k)}
\]
(是不是看起来就很不想做)
\(T = 70,\ a,b,c \leq 10 ^ 5,\ p \in [10 ^ 7,\ 1.05 \cdot 10 ^ 9] \cap \{\text{prime}\}\)
Analysis
虽然没什么好分析的,但是看到多测数据量并不大,可能我们不需要每次询问达到根号或者 \(\log\) 级别。
或者说这是三个循环的特性??
式子的整体形式原题面已经有了,有个最基本的拆分:
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \Big(\frac{i \cdot j}{\gcd(i, j) \cdot \gcd(i, k)}\Big) ^ {f(ty)}
\]
这样的话我们就相当于每个式子都要求两种子式子形如:
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c i ^ {f(ty)}
\]
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \gcd(i, j) ^ {f(ty)}
\]
Solution
就先默认 \(a \leq b \leq c\) 了。
\(1. f(ty) = 1\)
①
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c i
\]
看得出这玩意只和 \(i\) 有关系:
\[\Rightarrow \Big( \prod_{i = 1} ^ a i \Big) ^ {b \cdot c}
\]
预处理阶乘就行了,时间 \(O(n + T\log n)\) 。
②
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \gcd(i, j)
\]
只和其中两项有关,合并一个,然后按照最正常的套路,改枚举 \(\gcd\) :
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{i = 1}^{\large \lfloor \frac{a}{d} \rfloor \\}\sum_{j = 1}^{\large \lfloor \frac{b}{d} \rfloor \\}[\gcd(i, j) = 1]}\Big) ^ c
\]
套用莫比的式子有:
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{i = 1}^{\large \lfloor \frac{a}{d} \rfloor \\}\sum_{j = 1}^{\large \lfloor \frac{b}{d} \rfloor \\}\sum_{\large k\ | \gcd(i, j)}}\Big) ^ c
\]
然后把 k 改成枚举 \(\gcd\) 该换顺序,可以去掉两个循环:
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{k = 1} \mu(k) \large \lfloor \frac{a}{dk} \rfloor \lfloor \frac{b}{dk} \rfloor \\} \Big) ^ c
\]
再交换枚举顺序,令 \(T = dk\) ,有:
\[\Rightarrow \Bigg( \prod_{T = 1} \Big(\prod_{d | T} d ^ {\mu(\large \frac{T}{d}\\)} \Big) ^ { \large \lfloor \frac{a}{T} \rfloor \lfloor \frac{b}{T} \rfloor \\} \Bigg) ^ c
\]
小括号里面的东西是可以预处理的,具体地,对于每个 \(d\) 去枚举他的倍数算贡献;外面一层的可以数论分块,时间 \(O(n\ln n + T\sqrt n \log n)\)
(据说这玩意的形式叫狄利克雷卷积,但按定义来其实就行了)
\(2. f(ty) = i \cdot j \cdot k\)
③
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c i ^ {i \cdot j \cdot k}
\]
从某种程度上说还是只和 \(i\) 有关,但是原来对于后面两个连乘符号每次的次数贡献都是 \(1\) ,现在变成了一个变量,放到次数上就是:
\[\Rightarrow \prod_{i = 1} ^ a i ^ {i \cdot \sum j \cdot \sum k}
\]
预处理并令 \(su(x) = \sum_{i = 1} ^ x i\) ,预处理之后所求即可简化成:
\[\Rightarrow \Big( \prod_{i = 1} ^ a i ^ i \Big) ^ { su(b) \cdot su(c)}
\]
和第一问类似的预处理阶乘就行了,时间 \(O(n\log n + T\log n)\) 。
④
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \gcd(i, j) ^ {i \cdot j \cdot k}
\]
同样先合并 \(k\) ,然后按照老套路枚举因数:
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{i = 1}^{\large \lfloor \frac{a}{d} \rfloor \\}\sum_{j = 1}^{\large \lfloor \frac{b}{d} \rfloor \\} id \cdot jd \cdot [\gcd(i, j) = 1]}\Big) ^ {su(c)}
\]
套莫比的那个式子:
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{i = 1}^{\large \lfloor \frac{a}{d} \rfloor \\}\sum_{j = 1}^{\large \lfloor \frac{b}{d} \rfloor \\} id \cdot jd \cdot \sum_{\large k\ | \gcd(i, j)} \mu(k)}\Big) ^ {su(c)}
\]
再交换枚举顺序,改成枚举 \(\gcd\) ,处理掉两个循环,同样里面存在的 \(i\) 和 \(j\) 会再次提出来一个 \(\gcd\) ,有:
\[\Rightarrow \Big(\prod_{d = 1} ^ a d ^ {\sum_{k = 1} (idk) \cdot (jdk) \cdot \mu(k) \cdot su(\large \lfloor \frac{a}{dk} \rfloor \\) \cdot su(\large \lfloor \frac{b}{dk} \rfloor \\)}\Big) ^ {su(c)}
\]
改换 \(k\) 的枚举顺序,并令 \(T = dk\) ,有:
\[\Rightarrow \Bigg( \prod_{T = 1} \Big(\prod_{d | T} d ^ {\mu (\large \frac{T}{d} \\)}\Big) ^ {T ^ 2 \cdot su(\large \lfloor \frac{a}{T} \rfloor \\) \cdot su(\large \lfloor \frac{b}{T} \rfloor \\)} \Bigg) ^ {su(c)}
\]
预处理中间那个小括号的东西,同样也是枚举倍数,可以和 sub1 同样的用数论分块搞一搞就行了,时间 \(O(n\ln n \log n + T\sqrt n \log n)\) 。
\(3. f(ty) = gcd(i, j, k)\)
⑤
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c i ^ {\gcd(i, j, k)}
\]
这下没办法秒算了,先把两个连乘甩上去,但是还是必须按照套路枚举因数呐。。
\[\Rightarrow \prod_{d = 1} ^ a \prod_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} (id) ^ {d \cdot \sum_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} \sum_{k = 1} ^ {\large \lfloor \frac{c}{d} \rfloor \\} [\gcd(i, j, k) = 1]}
\]
套莫比的那个式子:
\[\Rightarrow \prod_{d = 1} ^ a \prod_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} (id) ^ {d \cdot \sum_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} \sum_{k = 1} ^ {\large \lfloor \frac{c}{d} \rfloor \\} \sum_{\large t\ | \gcd(i, j, k)} \mu(t)}
\]
把顺序一换,改成枚举 \(\gcd\) ,处理掉两个循环,改换 \(i\) 枚举范围,然后再从里面提取出一个 \(t\) 。
\[\Rightarrow \prod_{d = 1} \prod_{t = 1} \prod_{i = 1} ^ {\large \lfloor \frac{a}{dt} \rfloor \\} (idt) ^ {d \cdot \mu(t) \cdot \large \lfloor \frac{b}{dt} \rfloor \lfloor \frac{c}{dt} \rfloor \\}
\]
还是套路,令 \(T = dt\) ,有:
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{d | T} \Big( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} (iT) \Big) ^ {d \cdot \mu(\large \frac{T}{d} \\)} \Bigg) ^ {\large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
小括号里面的 \(iT\) 可以分开表示成阶乘和一个单独的数:
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{d | T} \Big( \text{fac}(\frac{T}{d}) \cdot T ^ {\large \lfloor \frac{a}{T} \rfloor \\} \Big) ^ {d \cdot \mu(\large \frac{T}{d} \\)} \Bigg) ^ {\large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
还能怎么化呢,发现在小括号外面一个非常眼熟的式子,有点像这个:
\[\text{id} * \mu = \varphi
\]
正好小括号里面完全和 \(d\) 没有关系,那就可以很快乐的合并了:
\[\Rightarrow \prod_{T = 1} \Big( \text{fac}(\frac{T}{d}) \cdot T ^ {\large \lfloor \frac{a}{T} \rfloor \\} \Big) ^ {\varphi (T) \cdot \large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
那其实这个东西就可以预处理 \(\varphi\) 之后套数论分块就可以了,时间 \(O(n\ln n \log n + T\sqrt n \log n)\) 。
⑥
\[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \gcd(i, j) ^ {\gcd(i, j, k)}
\]
其实我也没想到能和出题人解单次 \(O(n \log n)\) 吻合的这么好,属于是不偏不倚的掉进了出题人的坑??
这些都是后话。
一看就不对劲,两个 \(\gcd\) 先消哪个是个问题。。
然后看到上面是三个数合在一起,那必然很麻烦,选下面的!!
先选下面的
注意指数上是由三个数取 \(\gcd\) 的,所以不用一上来就先提出来一个 \(d\) 。
\[\Rightarrow \prod_{d = 1} d ^ {\Big(\sum_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} \sum_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} [\gcd(i, j) = 1]\Big) \cdot \Big(\sum_{k = 1} ^ c \gcd(d, k)\Big)}
\]
按照套路慢慢来:
\[\Rightarrow \prod_{d = 1} d ^ {\Big(\sum_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} \sum_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} \sum_{\large t\ | \gcd(i, j)}\Big) \cdot \Big(\sum_{k = 1} ^ c \gcd(d, k)\Big)}
\]
按照套路慢慢来(重复自动机):
\[\Rightarrow \prod_{d = 1} d ^ {\Big(\sum_{t = 1} \mu(t) \large \lfloor \frac{a}{dt} \rfloor \lfloor \frac{b}{dt} \rfloor \\ \Big) \cdot \Big(\sum_{k = 1} ^ c \gcd(d, k)\Big)}
\]
按照套路慢慢来(重复自动机加强版):
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{d | T} d ^ {\mu(\large\frac{T}{d} \\) \cdot \Big(\sum_{k = 1} ^ c \gcd(d, k)\Big)}\Bigg) ^ {\large \lfloor \frac{a}{T} \rfloor \lfloor \frac{b}{T} \rfloor \\ }
\]
现在可以看到前面的 \(\gcd\) 已经处理的差不多了,现在来继续考虑后面那个东西:
\[\sum_{k = 1} ^ c \gcd(d, k)
\]
继续再次枚举因数(满满的套路):
\[\Rightarrow \sum_{p | d} p \cdot \sum_{k = 1} ^ {\large \lfloor \frac{c}{p} \rfloor \\} [\gcd(\frac{d}{p}, k) = 1]
\]
\[\Rightarrow \sum_{p | d} p \cdot \sum_{qp | d} \mu(q) \cdot \lfloor \frac{c}{qp} \rfloor
\]
\[\Rightarrow \sum_{T^{'} | d} \lfloor \frac{c}{T^{'}} \rfloor \sum_{p | T^{'}} p \cdot \mu (\frac{T ^{'}}{p})
\]
噔噔噔,这玩意他又出现了:
\[\text{id} * \mu = \varphi
\]
\[\Rightarrow \sum_{T^{'} | d} \lfloor \frac{c}{T^{'}} \rfloor \cdot \varphi(T^{'})
\]
所以带回原来的式子:
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{d | T} d ^ {\mu(\large\frac{T}{d} \\) \cdot \Big(\sum_{T^{'} |\ d}\ \large \lfloor \frac{c}{T^{'}} \rfloor \\\cdot \varphi(T^{'})\Big)}\Bigg) ^ {\large \lfloor \frac{a}{T} \rfloor \lfloor \frac{b}{T} \rfloor \\ }
\]
能预处理之后 \(O(n \log n)\) 强行做吗,可以,但是前提是常数小。。
还是换一个吧。。
还是选上面的吧
我同学秒给出了这么选的理由:它在指数上,先消掉更好做,反正我是想不明白的了。。
注意这样的话上下面的 \(\gcd\) 就都要先提出 \(d\) 了。
\[\Rightarrow \prod_{d = 1} \prod_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} \Big(d \cdot \gcd(i, j)\Big) ^ {d \cdot \sum_{k = 1} ^ {\large \lfloor \frac{c}{d} \rfloor \\} [\gcd(i, j, k) = 1]}
\]
套路:
\[\Rightarrow \prod_{d = 1} \prod_{i = 1} ^ {\large \lfloor \frac{a}{d} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{d} \rfloor \\} \Big(d \cdot \gcd(i, j)\Big) ^ {d \cdot \sum_{k = 1} ^ {\large \lfloor \frac{c}{d} \rfloor \\} \sum_{\large t\ | \gcd(i, j, k)} \mu(t)}
\]
套路:
\[\Rightarrow \prod_{d = 1} \prod_{t = 1} \prod_{i = 1} ^ {\large \lfloor \frac{a}{dt} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{dt} \rfloor \\} \Big(dt \cdot \gcd(i, j)\Big) ^ {d \cdot \mu(t) \cdot \large \lfloor \frac{c}{dt} \rfloor}
\]
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{d | T} \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \Big(T \cdot \gcd(i, j)\Big) ^ {d \cdot \mu(\large \frac{T}{d} \\)}\Bigg) ^ {\large \lfloor \frac{c}{T} \rfloor}
\]
又可以把 \(d\) 甩上去:
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \Big(T \cdot \gcd(i, j)\Big) ^ {\sum_{d\ |\ T} d \cdot \mu(\large \frac{T}{d} \\)}\Bigg) ^ {\large \lfloor \frac{c}{T} \rfloor}
\]
噔噔噔,这玩意他又又出现了:
\[\text{id} * \mu = \varphi
\]
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \Big(T \cdot \gcd(i, j)\Big) ^ {\varphi(T)}\Bigg) ^ {\large \lfloor \frac{c}{T} \rfloor}
\]
还能推推,但是感觉有点怪熟悉的??
T 又出现了,并且看看 ⑤ 的式子:
\[\Rightarrow \prod_{T = 1} \Big( \text{fac}(\frac{T}{d}) \cdot T ^ {\large \lfloor \frac{a}{T} \rfloor \\} \Big) ^ {\varphi (T) \cdot \large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
\[\Rightarrow \prod_{T = 1} T ^ {\varphi (T) \cdot \large \lfloor \frac{a}{T} \rfloor \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\} \cdot \prod_{T = 1} \Big( \text{fac}(\frac{T}{d}) \Big) ^ {\varphi (T) \cdot \large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
再看看 ⑥ 的式子:
\[\Rightarrow \prod_{T = 1} \Bigg( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \Big(T \cdot \gcd(i, j)\Big) ^ {\varphi(T)}\Bigg) ^ {\large \lfloor \frac{c}{T} \rfloor}
\]
\[\Rightarrow \prod_{T = 1} T ^ {\varphi (T) \cdot \large \lfloor \frac{a}{T} \rfloor \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\} \cdot \prod_{T = 1} \Bigg( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \gcd(i, j)\Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
哇塞上下各两项,刚好消掉!!
那现在 ⑤ 更新成:
\[\prod_{T = 1} \Big( \text{fac}(\frac{T}{d}) \Big) ^ {\varphi (T) \cdot \large \lfloor \frac{b}{T} \rfloor \lfloor \frac{c}{T} \rfloor \\}
\]
⑥ 更新成:
\[\prod_{T = 1} \Bigg( \prod_{i = 1} ^ {\large \lfloor \frac{a}{T} \rfloor \\} \prod_{j = 1} ^ {\large \lfloor \frac{b}{T} \rfloor \\} \gcd(i, j)\Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
继续看 ⑥ :
\[\prod_{T = 1} \Bigg( \prod_{p = 1} p ^ {\sum_{i = 1} ^ {\large \lfloor \frac{a}{pT} \rfloor \\} \sum_{j = 1} ^ {\large \lfloor \frac{b}{pT} \rfloor \\} [\gcd(i, j) = 1]}\Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
\[\prod_{T = 1} \Bigg( \prod_{p = 1} p ^ {\sum_{i = 1} ^ {\large \lfloor \frac{a}{pT} \rfloor \\} \sum_{j = 1} ^ {\large \lfloor \frac{b}{pT} \rfloor \\} \sum_{\large q\ | \gcd(i, j)\\} \mu(q)}\Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
\[\prod_{T = 1} \Bigg( \prod_{p = 1} p ^ { \sum_{q = 1} \mu(q) \cdot \large \lfloor \frac{a}{pTq} \rfloor \lfloor \frac{b}{pTq} \rfloor \\} \Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
\[\prod_{T = 1} \Bigg(\prod_{T ^{'} = 1} \Big( \prod_{p | T ^{'}} p ^ { \mu(\large \frac{T ^ {'}}{p} \\)} \Big)^ {\large \lfloor \frac{a}{TT ^ {'}} \rfloor \lfloor \frac{b}{TT ^ {'}} \rfloor \\} \Bigg) ^ {\varphi(T) \cdot \large \lfloor \frac{c}{T} \rfloor}
\]
看起来只要预处理里面小括号的东西,做两次数论分块就可以做完了呢。
其实还没完:
⑤ 式子剩下的是一层数论分块加 \(\text{fac}\) ,⑥ 剩下的是两层数论分块加 \(\prod_{p | T ^{'}} p ^ { \mu(\large \frac{T ^ {'}}{p} \\)}\) 。
奈奈地这 ** 就是一层数论分块套了一个答案 1 ,然后在最外围加上一层 \(\varphi\) 嘛。
代码 -= 1kb 。
时间 \(O(n\ln n \log n + T\sqrt {n \sqrt n} \log n)\) 。
Note
一些像 \(su\) 和 \(\varphi\) 等函数用处仅存在于指数上的,计算取模是 \(\varphi(\text{mod}) = \text{mod} - 1\)
上文仅仅讲解了两个式子,但是如若要还原到原来的式子。要求前者对于 \(i\) 和 \(j\) 的值,求后者对于 \((i, j)\) 和 \((i, k)\) 的倒数值(因为 \(\text{mod}\) 为质数所以说也就是一个 \(\log\) 的事)
Code
Code
/*
*/
#include
using namespace std;
typedef long long ll;
const int N = 1e5 + 10, M = 72;
int a[M], b[M], c[M], mod, mx, pri[N], tot, mu[N], phi[N];
bool vis[N];
int fac[N], f1[N], if1[N], fic[N], f2[N], if2[N], su[N];
struct ios {
inline char gc() {
static const int IN_LEN = 1 << 18 | 1;
static char buf[IN_LEN], *s, *t;
return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
}
template inline ios & operator >> (_Tp & x) {
static char ch, sig; ch = gc(); sig = 0;
for (; !isdigit(ch); ch = gc()) {if (ch == -1) return *this; sig |= (ch =='-');}
for (x = 0; isdigit(ch); ch = gc()) x = (x << 3) + (x << 1) + (ch ^ 48);
sig && (x = -x); return *this;
}
} io;
inline double dead() {
char ch = io.gc();
ll s = 0, w = 1, k = 0;
double m = 1; bool is = 0;
while (!isdigit(ch)) {if (ch == '-') w = -1; ch = io.gc();}
while (isdigit(ch) || ch == '.') {
if (ch == '.') is = 1;
else if (!is) s = (s << 3) + (s << 1) + (ch ^ 48);
else k = (k << 3) + (k << 1) + (ch ^ 48), m *= 0.1;
ch = io.gc();
}
return (m * k + s) * w;
}
inline string sead() {
char ch = io.gc();
string s;
while (ch == ' ' || ch == '\n' || ch == '\t') ch = io.gc();
while (ch != ' ' && ch != '\n' && ch != '\t') s += ch, ch = io.gc();
return s;
}
inline int mul(int a, int b) {return 1ll * a * b % mod;}
inline int mull(int a, int b) {return 1ll * a * b % (mod - 1);}
inline int ksm(int a, int b) {
int tmp = 1;
for (; b; b >>= 1, a = mul(a, a)) if (b & 1) tmp = mul(tmp, a);
return tmp;
}
inline void init() {
mu[1] = phi[1] = 1;
fac[0] = fac[1] = f1[0] = f1[1] = if1[0] = if1[1] = 1;
fic[0] = fic[1] = f2[0] = f2[1] = if2[0] = if2[1] = su[1] = 1;
for (int i = 2; i <= mx; ++i) {
if (!vis[i]) mu[pri[++tot] = i] = -1, phi[i] = i - 1;
for (int j = 1; j <= tot && pri[j] * i <= mx; ++j) {
vis[i * pri[j]] = 1;
if (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]];
}
f1[i] = if1[i] = 1;
fac[i] = mul(fac[i - 1], i);
f2[i] = if2[i] = 1;
fic[i] = mul(fic[i - 1], ksm(i, i));
su[i] = (su[i - 1] + i) % (mod - 1);
}
for (int i = 1; i <= mx; ++i) {
(phi[i] += phi[i - 1]) %= (mod - 1);
for (int j = i, k = 1; j <= mx; j += i, ++k) {
f1[j] = mul(f1[j], ksm(i, (mod - 1 + mu[k]) % (mod - 1)));
}
}
for (int i = 1; i <= mx; ++i) {
f2[i] = ksm(f1[i], mull(i, i));
f1[i] = mul(f1[i], f1[i - 1]); if1[i] = ksm(f1[i], mod - 2);
f2[i] = mul(f2[i], f2[i - 1]); if2[i] = ksm(f2[i], mod - 2);
}
}
inline int F1(int n, int m) {
int ans = 1;
if (n > m) swap(n, m);
for (int l = 1, r = 0; l <= n; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans = mul(ans, ksm(mul(f1[r], if1[l - 1]), mull(n / l, m / l)));
}
return ans;
}
inline int F2(int n, int m) {
int ans = 1;
if (n > m) swap(n, m);
for (int l = 1, r = 0; l <= n; l = r + 1) {
r = min(n / (n / l), m / (m / l));
ans = mul(ans, ksm(mul(f2[r], if2[l - 1]), mull(su[n / l], su[m / l])));
}
return ans;
}
inline int sub1(int a, int b, int c) {
int res, ret;
res = mul(ksm(fac[a], mull(b, c)), ksm(fac[b], mull(a, c)));
ret = ksm(mul(ksm(F1(a, b), c), ksm(F1(a, c), b)), mod - 2);
return mul(res, ret);
}
inline int sub2(int a, int b, int c) {
int res, ret;
res = ksm(mul(ksm(fic[a], su[b]), ksm(fic[b], su[a])), su[c]);
ret = ksm(mul(ksm(F2(a, b), su[c]), ksm(F2(a, c), su[b])), mod - 2);
return mul(res, ret);
}
inline int sub3(int a, int b, int c) {
int ans3 = 1, lim = min(a, min(b, c));
//不要想当然from peterwuyihong
for (int l = 1, r = 0; l <= lim; l = r + 1) {
r = min(a / (a / l), min(b / (b / l), c / (c / l)));
ans3 = mul(ans3, ksm(sub1(a / l, b / l, c / l), (phi[r] - phi[l - 1] + mod - 1) % (mod - 1)));
}
return ans3;
}
inline void mian(int a, int b, int c) {
printf("%d %d %d\n", sub1(a, b, c), sub2(a, b, c), sub3(a, b, c));
}
int main() {
int T; io >> T >> mod;
for (int i = 1; i <= T; ++i) {
io >> a[i] >> b[i] >> c[i];
mx = max(max(mx, c[i]), max(a[i], b[i]));
}
init();
for (int i = 1; i <= T; ++i) mian(a[i], b[i], c[i]);
return 0;
}