Description
You are given a positive integer D. Let’s build the following graph from it:
each vertex is a divisor of D (not necessarily prime, 1 and D itself are also included);
two vertices x and y (x>y) have an undirected edge between them if x is divisible by y and xy is a prime;
the weight of an edge is the number of divisors of x that are not divisors of y.
For example, here is the graph for D=12:
Edge (4,12) has weight 3 because 12 has divisors [1,2,3,4,6,12] and 4 has divisors [1,2,4]. Thus, there are 3 divisors of 12 that are not divisors of 4 — [3,6,12].
There is no edge between 3 and 2 because 3 is not divisible by 2. There is no edge between 12 and 3 because 123=4 is not a prime.
Let the length of the path between some vertices v and u in the graph be the total weight of edges on it. For example, path [(1,2),(2,6),(6,12),(12,4),(4,2),(2,6)] has length 1+2+2+3+1+2=11. The empty path has length 0.
So the shortest path between two vertices v and u is the path that has the minimal possible length.
Two paths a and b are different if there is either a different number of edges in them or there is a position i such that ai and bi are different edges.
You are given q queries of the following form:
v u — calculate the number of the shortest paths between vertices v and u.
The answer for each query might be large so print it modulo 998244353.
Input
The first line contains a single integer D (1≤D≤1015) — the number the graph is built from.
The second line contains a single integer q (1≤q≤3⋅105) — the number of queries.
Each of the next q lines contains two integers v and u (1≤v,u≤D). It is guaranteed that D is divisible by both v and u (both v and u are divisors of D).
Output
Print q integers — for each query output the number of the shortest paths between the two given vertices modulo 998244353.
对于两个点之间的最短路径就是一直除或者一直乘,除的顺序和乘的顺序是不影响总权重的。
a->b->c的总权重为a的权重-b的权重+b的权重-c的权重…
选择的顺序通过组合数学来求…
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5;
const int inf=0x3f3f3f3f;
const int mod=998244353;
ll ans[maxn],fac[maxn],a[maxn];
ll pow_(ll a,ll b){
a%=mod;
ll ans=1;
while(b){
if(b&1)ans=(ans*a)%mod;
a=(a*a)%mod;
b>>=1;
}
return ans;
}
ll gcd(ll a,ll b){
return b?gcd(b,a%b):a;
}
ll C(ll n,ll m){
return (fac[n]*pow_(fac[n-m]*fac[m],mod-2))%mod;
}
ll cal(ll x){
ll ans=1;
int cnt=0,all=0;
for(ll i=2;i*i<=x;++i){
int num=0;
while(x%i==0){
++num;
x/=i;
}
all+=num;
if(num)a[++cnt]=num;
}
if(x>1||cnt==0)a[++cnt]=1,++all;
for(int i=1;i<=cnt;++i){
ans=(ans*C(all,a[i]))%mod;
all-=a[i];
}
return ans;
}
int main()
{
ll d,u,v,q;
map<ll,ll>mp;
scanf("%lld %lld",&d,&q);
fac[0]=fac[1]=1;
for(int i=2;i<maxn;++i)fac[i]=(fac[i-1]*i)%mod;
while(q--){
scanf("%lld %lld",&u,&v);
ll g=gcd(u,v);
u/=g,v/=g;
if(mp[u]==0)mp[u]=cal(u);
if(mp[v]==0)mp[v]=cal(v);
printf("%lld\n",(mp[u]*mp[v]+mod)%mod);
}
return 0;
}