CF1334E Divisor Paths 题解

分析

放一张题面里的图。

能发现走一条边就是除掉或加入一个质因子。

\(x\) 走到 \(y\) 的最短路,一定是先除掉若干质因子,再加入若干质因子。中间那个临界点是 \(d=\gcd(x,y)\)

然后考虑一条节点不断变小的路径,发现它的边权和可以消去中间项,只和首位有关。因此 \((x \rightarrow d)\)\((y \rightarrow d)\) 的最短路和具体消去质因子的顺序无关。

\((x \rightarrow d)\) 为例。把 \(\frac{x}{d}\) 分解为 \(\prod_{i=1}^m p_i^{e_i}\),则消去质因子的方案数是 \[ f\Big(\frac{x}{d}\Big) = \frac{(\sum_{i=1}^m e_i)!}{\prod_{i=1}^m(e_i!)} \] 最终答案就是 \(f\Big(\frac{x}{d}\Big) \times f\Big(\frac{y}{d}\Big)\)

CODE

#include<bits/stdc++.h>
using namespace std;
#define int long long
int read() {
	int a=0, f=1; char c=getchar();
	while(!isdigit(c)) {
		if(c=='-') f=-1;
		c=getchar();
	}
	while(isdigit(c)) a=a*10+c-'0', c=getchar();
	return a*f;
}
const int mod=998244353;
int D, q, cnt, d[100], fac[100];
// 虽然D很大,但是质因数个数和质因数指数都是log级别的
int fp(int a,int b) {
	int c=1;
	for(;b;a=a*a%mod,b>>=1) if(b&1) c=c*a%mod;
	return c;
}
int calc(int x) {
	int p=0, q=1;
	for(int i=1;i<=cnt;++i) if(x%d[i]==0) {
		int e=0;
		while(x%d[i]==0) x/=d[i], ++e;
		p+=e, (q*=fac[e])%=mod;
	}
	return fac[p]*fp(q,mod-2)%mod;
}
int gcd(int x,int y) { return y? gcd(y,x%y):x; }
signed main() {
	D=read(), q=read();
	for(int i=2;i*i<=D;++i) if(D%i==0) {
		while(D%i==0) D/=i;
		d[++cnt]=i;
	}
	if(D>1) d[++cnt]=D;
	fac[0]=fac[1]=1;
	for(int i=2;i<=100;++i) fac[i]=fac[i-1]*i%mod;
	while(q--) {
		int x=read(), y=read();
		int z=gcd(x,y);
		printf("%lld\n",calc(x/z)*calc(y/z)%mod);
	}
}

CF1334E Divisor Paths 题解
https://yozora0908.github.io/2022/cf1344e-solution/
作者
yozora0908
发布于
2022年8月16日
许可协议