Codeforces1334E - Divisor Paths

Description

You are given a positive integer D. Let’s build the following graph from it:c++

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:web

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].svg

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.ui

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.spa

So the shortest path between two vertices v and u is the path that has the minimal possible length.code

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.orm

You are given q queries of the following form:xml

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.token

Input

The first line contains a single integer D (1≤D≤1015) — the number the graph is built from.ip

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;
}