Educational Codeforces Round 85 (Rated for Div. 2)E. Divisor Paths(數論,思維)

E. Divisor Paths

time limit per test

3 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given a positive integer DD. Let's build the following graph from it:

  • each vertex is a divisor of DD (not necessarily prime, 11 and DD itself are also included);
  • two vertices xx and yy (x>yx>y) have an undirected edge between them if xx is divisible by yy and xyxy is a prime;
  • the weight of an edge is the number of divisors of xx that are not divisors of yy.

For example, here is the graph for D=12D=12:

Edge (4,12)(4,12) has weight 33 because 1212 has divisors [1,2,3,4,6,12][1,2,3,4,6,12] and 44 has divisors [1,2,4][1,2,4]. Thus, there are 33 divisors of 1212 that are not divisors of 44 — [3,6,12][3,6,12].

There is no edge between 33 and 22 because 33 is not divisible by 22. There is no edge between 1212 and 33 because 123=4123=4 is not a prime.

Let the length of the path between some vertices vv and uu 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)][(1,2),(2,6),(6,12),(12,4),(4,2),(2,6)] has length 1+2+2+3+1+2=111+2+2+3+1+2=11. The empty path has length 00.

So the shortest path between two vertices vv and uu is the path that has the minimal possible length.

Two paths aa and bb are different if there is either a different number of edges in them or there is a position ii such that aiai and bibi are different edges.

You are given qq queries of the following form:

  • vv uu — calculate the number of the shortest paths between vertices vv and uu.

The answer for each query might be large so print it modulo 998244353998244353.

Input

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

The second line contains a single integer qq (1≤q≤3⋅1051≤q≤3⋅105) — the number of queries.

Each of the next qq lines contains two integers vv and uu (1≤v,u≤D1≤v,u≤D). It is guaranteed that DD is divisible by both vv and uu (both vv and uu are divisors of DD).

Output

Print qq integers — for each query output the number of the shortest paths between the two given vertices modulo 998244353998244353.

Examples

input

Copy

12
3
4 4
12 1
3 4

output

Copy

1
3
1

input

Copy

1
1
1 1

output

Copy

1

input

Copy

288807105787200
4
46 482955026400
12556830686400 897
414 12556830686400
4443186242880 325

output

Copy

547558588
277147129
457421435
702277623

Note

In the first example:

  • The first query is only the empty path — length 00;
  • The second query are paths [(12,4),(4,2),(2,1)][(12,4),(4,2),(2,1)] (length 3+1+1=53+1+1=5), [(12,6),(6,2),(2,1)][(12,6),(6,2),(2,1)] (length 2+2+1=52+2+1=5) and [(12,6),(6,3),(3,1)][(12,6),(6,3),(3,1)] (length 2+2+1=52+2+1=5).
  • The third query is only the path [(3,1),(1,2),(2,4)][(3,1),(1,2),(2,4)] (length 1+1+1=31+1+1=3).

題意:給你一個數D(<=1e15),D的所有因子(包括1和它本身)作爲節點構成無向圖,對於某兩個因子x,y,若x%y==0且x/y爲質數,那麼x,y之間就存在一條長爲 x的因子數-y的因子數 的邊,接下來q(<=3e5)次詢問,每次詢問a,b,問a到b之間的最短路徑都多少條。

思路:看了大佬們的解析,長見識了。

經典的組合數問題:x不斷除以它的質因子,直到變成1 的方案數爲x的質因子的冪次之和的階乘 除以 x的每個質因子的冪次的階乘之積。

分析:顯然圖中的點很少,若x,y之間有邊,顯然x%y==0。我們假設詢問的兩個點x,y,有x%y==0,那麼顯然最短路就是x除以質因子直到變成y經過的路徑(路徑長度爲因子數之差)。就相當於x除以質因子變成y的方案數,也就是x/y除以它的質因子變成1的方案數。

若x%y!=0,則x到y的路徑必然會經過一個數k,其中x%k==0且y%k==0,這個k顯然就是x,y的gcd。因此我們直接用map預處理方案數,然後直接map回答,複雜度可以接受。

代碼:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(register int i=(a);i<=(b);i++)
#define dep(i,a,b) for(register int i=(a);i>=(b);i--)
using namespace std;
const int maxn=3e5+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
const ll mo=998244353;
ll n,m,k;
int q;
ll ans,tmp,cnt;
int flag;
ll jc[maxn];
ll power(ll a,ll n){
    ll sum=1;
    while(n){
        if(n&1) sum=sum*a%mo;
        n>>=1;
        a=a*a%mo;
    }
    return sum;
}
map<ll,ll>mp;
ll cal(ll x){
    ll sum1=0,sum2=1;
    for(ll i=2;i*i<=x;i++) if(x%i==0){
        ll num=0;
        while(x%i==0){x/=i;num++;}
        sum2=sum2*power(jc[num],mo-2)%mo;
        sum1+=num;
    }
    if(x>1) sum1++;
    sum1=jc[sum1]*sum2%mo;
    return sum1;
}
int main()
{
    jc[0]=1;
    rep(i,1,maxn-1) jc[i]=jc[i-1]*i%mo;
    int T,cas=1;
    //scanf("%d",&T);
    //while(T--)
    {
        scanf("%lld",&n);
        for(ll i=1;i*i<=n;i++){
            if(n%i==0){
                mp[i]=cal(i);
                mp[n/i]=cal(n/i);
            }
        }
        scanf("%d",&q);
        rep(i,1,q){
            ll x,y;
            scanf("%lld%lld",&x,&y);
            ll k=__gcd(x,y);
            ll as=mp[x/k]*mp[y/k]%mo;
            printf("%lld\n",as);
        }
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章