Solution #
First let’s factor D D D , so D = p 1 e 1 p 2 e 2 … p k e k D=p_1^{e_1}p_2^{e_2}\dots p_k^{e_k} D = p 1 e 1 p 2 e 2 … p k e k . According to the definition, to factors are connected iff they differ by only one prime factor. And the weight of the edge is d ( x ) − d ( y ) d(x)-d(y) d ( x ) − d ( y ) where d ( i ) d(i) d ( i ) is the number of factors of i i i . So the length of a path where v 1 < v 2 < ⋯ < v k v_1<v_2<\dots<v_k v 1 < v 2 < ⋯ < v k is d ( v k ) − d ( v i ) d(v_k)-d(v_i) d ( v k ) − d ( v i )
There are only two types of paths between x x x and y y y , one is x → gcd ( x , y ) → y x \rightarrow\gcd(x,y)\rightarrow y x → g cd( x , y ) → y and the other is x → lcm ( x , y ) → y x \rightarrow \operatorname{lcm}(x,y) \rightarrow y x → lcm ( x , y ) → y . The length of the path of the first type is
d ( x ) − d ( gcd ( x , y ) ) + d ( y ) + d ( gcd ( x , y ) ) = d ( x ) + d ( y ) − 2 ⋅ d ( gcd ( x , y ) ) d(x)-d(\gcd(x,y))+d(y)+d(\gcd(x,y))=d(x)+d(y)-2\cdot d(\gcd(x,y)) d ( x ) − d ( g cd( x , y )) + d ( y ) + d ( g cd( x , y )) = d ( x ) + d ( y ) − 2 ⋅ d ( g cd( x , y ))
The length of the second type is
d ( lcm ( x , y ) ) − d ( x ) + d ( lcm ( x , y ) ) − d ( y ) = 2 ⋅ d ( lcm ( x , y ) ) − d ( x ) − d ( y ) d(\operatorname{lcm}(x,y))-d(x)+d(\operatorname{lcm}(x,y))-d(y)=2\cdot d(\operatorname{lcm}(x,y))-d(x)-d(y) d ( lcm ( x , y )) − d ( x ) + d ( lcm ( x , y )) − d ( y ) = 2 ⋅ d ( lcm ( x , y )) − d ( x ) − d ( y )
Intuition tells us first type is always the shortest path.
All we need now is to calculate the number of shortest paths. Let x gcd ( x , y ) = p 1 e 1 p 2 e 2 … p k e k \frac x {\gcd(x,y)}=p_1^{e_1}p_2^{e_2}\dots p_k^{e_k} g c d ( x , y ) x = p 1 e 1 p 2 e 2 … p k e k . The number of shortest path between x x x and gcd ( x , y ) \gcd(x,y) g cd( x , y ) is
( e 1 + e 2 + … e k ) ! e 1 ! ⋅ e 2 ! ⋅ … ⋅ e k ! \dfrac {(e_1+e_2+\dots e_k)!}{e_1!\cdot e_2!\cdot\ldots\cdot e_k!} e 1 ! ⋅ e 2 ! ⋅ … ⋅ e k ! ( e 1 + e 2 + … e k )!
Similarly we can calculate the number of paths between y y y and gcd ( x , y ) \gcd(x,y) g cd( x , y ) .
Code #
# include < bits/stdc++.h >
# define forn ( i , n ) for ( int i = 0 ; i < int ( n ) ; ++ i )
# define for1 ( i , n ) for ( int i = 1 ; i <= int ( n ) ; ++ i )
# define fore ( i , l , r ) for ( int i = int ( l ) ; i <= int ( r ) ; ++ i )
# define ford ( i , n ) for ( int i = int ( n ) - 1 ; i >= 0 ; -- i )
# define pb push_back
# define eb emplace_back
# define ms ( a , x ) memset ( a , x , sizeof ( a ))
# define F first
# define S second
# define endl '\n'
# define all ( x ) ( x ) . begin () , ( x ) . end ()
using namespace std ;
typedef long long ll ;
typedef pair <int , int> pii ;
const int INF = 0x 3f3f3f3f ;
mt19937 gen ( chrono :: high_resolution_clock :: now () . time_since_epoch () . count ()) ;
template < typename ... Args >
void write ( Args ... args ) { (( cout << args << " " ) , ... ) ; cout << endl ; }
constexpr ll mod = 998244353 ;
ll binpow ( ll a , int b ){
ll res = 1 ;
for ( ; b ; b >>= 1 ){
if (b & 1 ) res = res * a % mod ;
a = a * a % mod ;
}
return res ;
}
int main () {
ios :: sync_with_stdio ( false ) ;
cin . tie ( nullptr ) ;
ll n ;
cin >> n ;
vector < ll > factor ;
for ( ll f = 2 ; f * f <= n ; f ++ ){
if (n % f == 0 ){
factor . push_back (f) ;
while (n % f == 0 ) n /= f ;
}
}
if ( n > 1 ) factor . push_back ( n ) ;
array < ll , 1000 > fac , inv ;
fac [ 0 ] = inv [ 0 ] = 1 ;
for ( int i = 1 ; i < 1000 ; i ++ ) fac [ i ] = fac [ i - 1 ] * i % mod ;
inv [ 999 ] = binpow ( fac [ 999 ] , mod - 2 ) ;
for ( int i = 998 ; i > 0 ; i -- ) inv [ i ] = inv [ i + 1 ] * ( i + 1 ) % mod ;
auto count =[ & ] ( ll x , ll y ){
x /= y ;
ll ret = 1 , sum = 0 ;
for ( auto it : factor ){
int tmp = 0 ;
while (x % it == 0 ){
tmp ++;
x /= it ;
}
ret = ret * inv [tmp] % mod ;
sum += tmp ;
}
ret = ret * fac [ sum ] % mod ;
return ret ;
} ;
int q ;
cin >> q ;
while ( q -- ){
ll x , y ;
cin >> x >> y ;
ll g = gcd (x , y) ;
cout << count (x , g) * count (y , g) % mod << endl ;
}
return 0 ;
}