「MtOI2019」幽灵乐团

前言

\(\color{black}{{\rm C}}\color{red}{{\rm YJian}}\) 出的大毒瘤题,集 \(3\)\(1\) ,卡常,还有数学几大令人上吐下泻的毒瘤于一体,充分考察了选手的耐心,所以说静下心来还是非常有思考价值的。

注意本题大量运用了莫反的套路,所以推荐先做几道莫反的题练练手。

这是我做这题胡写的推导(你要实在不想看这篇题解看看这个也不失为上上策)

Description

\(T\) 次询问,每次给定 \(a\)\(b\)\(c\) ,求下列三个式子的值:

  1. \[\prod_{i = 1} ^ a \prod_{j = 1} ^ b \prod_{k = 1} ^ c \frac{\text{lcm}(i, j)}{\gcd(i, k)} \]

  2. \[\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} \]

  3. \[\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;
}

posted @ 2022-06-08 21:53  Illusory_dimes  阅读(30)  评论(1编辑  收藏  举报