Educational Codeforces Round 85 (Rated for Div. 2) E Divisor Paths
最短路:x->gcd(x,y)->y
然后就是一个有重复数字的错排问题,
设每种数字分别出现k1,k2,k3…kp次,并假设该错排的答案为f
那么f*k1!*k2!k3!…*kp!= ( sigma(ki) )!
#pragma GCC optimize(2)
#include<bits/stdc++.h>
#define ls rt<<1
#define rs rt<<1|1
#define pb push_back
#define fi first
#define se second
#define yes puts("YES")
#define no puts("NO")
#define ios ios::sync_with_stdio(0);
using namespace std;
typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;
const int maxn = 1e6 + 6;
const LL inf = 0x3f3f3f3f3f3f3f3f;
const int mod = 998244353;
LL qp(LL x,LL y){LL ans=1;x%=mod;while(y){if(y&1) ans=ans*x%mod;x=x*x%mod;y>>=1;}return ans;}
LL inv(LL x){return qp(x,mod-2);}
//head
vector<LL>x;
LL fac[maxn],fnv[maxn];
LL way(LL u){
LL f=1,s=0,len=x.size();
for(int i=0;i<len;i++){
int p=0;
while(u%x[i]==0) u/=x[i],p++;
f=f*fnv[p]%mod;
s+=p;
}
return f*fac[s]%mod;
}
int main(){
fac[0]=fnv[0]=1;
for(int i=1;i<=100000;i++) {
fac[i]=fac[i-1]*i%mod;
fnv[i]=qp(fac[i],mod-2);
}
LL d;scanf("%lld",&d);
for(LL i=2;i*i<=d;i++){
if(d%i==0){
x.pb(i);
while(d%i==0) d/=i;
}
}
if(d>1) x.pb(d);
int q;scanf("%d",&q);
while(q--){
LL u,v;scanf("%lld%lld",&u,&v);
LL gcd=__gcd(u,v);
printf("%lld\n",way(u/gcd)*way(v/gcd)%mod);
}
}