D. Count GCD

D. Count GCD

You are given two integers $n$ and $m$ and an array $a$ of $n$ integers. For each $1 \le i \le n$ it holds that $1 \le a_i \le m$.

Your task is to count the number of different arrays $b$ of length $n$ such that:

  • $1 \le b_i \le m$ for each $1 \le i \le n$, and
  • $\gcd(b_1,b_2,b_3,...,b_i) = a_i$ for each $1 \le i \le n$.

Here $\gcd(a_1,a_2,\dots,a_i)$ denotes the greatest common divisor (GCD) of integers $a_1,a_2,\ldots,a_i$.

Since this number can be too large, print it modulo $998\,244\,353$.

Input

Each test consist of multiple test cases. The first line contains a single integer $t$ ($1 \le t \le 100$) — the number of test cases. The description of test cases follows.

The first line of each test case contains two integers $n$ and $m$ ($1 \le n \le 2 \cdot 10^5$, $1 \le m \le 10^9$) — the length of the array $a$ and the maximum possible value of the element.

The second line of each test case contains $n$ integers $a_1, a_2, \ldots, a_n$ ($1 \le a_i \le m$) — the elements of the array $a$.

It is guaranteed that the sum of $n$ across all test cases doesn't exceed $2 \cdot 10^5$.

Output

For each test case, print a single integer — the number of different arrays satisfying the conditions above. Since this number can be large, print it modulo $998\,244\,353$.

Example

input

5
3 5
4 2 1
2 1
1 1
5 50
2 3 5 2 3
4 1000000000
60 30 1 1
2 1000000000
1000000000 2

output

3
1
0
595458194
200000000

Note

In the first test case, the possible arrays $b$ are:

  • $[4,2,1]$;
  • $[4,2,3]$;
  • $[4,2,5]$.

In the second test case, the only array satisfying the demands is $[1,1]$.

In the third test case, it can be proven no such array exists.

 

解题思路

  由于有$\gcd(b_1,b_2,b_3,...,b_{i-1}) = a_{i-1}$,因此容易发现$a_{i} = \gcd(b_1,b_2,b_3,...,b_{i-1}, b_{i}) = \gcd(a_{i-1}, b_{i})$。因此如果$a_{i} \nmid a_{i-1}$,那么就一定无解,即满足条件的$b$数组数量为$0$。

  否则,由于$a_{i} = \gcd(a_{i-1}, b_{i})$,因此$b_{i}$应该是$a_{i}$的倍数,即$b_{i} = k \cdot a_{i}$,其中$1 \leq k \leq \left\lfloor \frac{m}{a_i} \right\rfloor$。同时还需要注意到$a_{i-1}, b_{i}$要满足$\gcd(\frac{a_{i-1}}{a_i}, \frac{b_i}{a_i}) = 1$,即$a_{i-1}$和$b_{i}$除去最大公因子后,$\frac{b_i}{a_i}$应该与$\frac{a_{i-1}}{a_i}$互质,否则最大公因子就不是$a_i$了。因此选择的$k$还应该满足不能含有$\frac{a_{i-1}}{a_i}$的任何一个质因子,即满足$\gcd(k, \frac{a_{i-1}}{a_i}) = 1$。这个就可以用容斥原理来实现。

  因此需要先对$\frac{a_{i-1}}{a_i}$分解质因子,由于在不超过${10}^{9}$的数中分解得到不同的质因子的个数最多不超过$9$个($2 \times 3 \times 5 \times 7 \times 11 \times 13 \times 17 \times 19 \times 23 = 223\,092\,870 < {10}^{9}$),因此为了实现方便这里容斥原理可以通过二进制枚举的方式来实现。

  AC代码如下:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long LL;
 5 
 6 const int N = 2e5 + 10, mod = 998244353;
 7 
 8 int a[N];
 9 
10 vector<int> divide(int x) {
11     vector<int> fs;
12     for (int i = 2; i <= x / i; i++) {
13         if (x % i == 0) {
14             fs.push_back(i);
15             while (x % i == 0) {
16                 x /= i;
17             }
18         }
19     }
20     if (x > 1) fs.push_back(x);
21     return fs;
22 }
23 
24 void solve() {
25     int n, m;
26     scanf("%d %d", &n, &m);
27     for (int i = 0; i < n; i++) {
28         scanf("%d", a + i);
29     }
30     LL ret = 1;
31     for (int i = 1; i < n; i++) {
32         if (a[i - 1] % a[i]) {    // a[i]不能整除a[i-1],无解 
33             ret = 0;
34             break;
35         }
36         else {
37             // a[i-1]/a[i]要与k互质 
38             vector<int> fs = divide(a[i - 1] / a[i]);    // 分解质因数 
39             LL k = m / a[i], s = 0;    // s是容斥原理的结果,即满足条件的k的个数 
40             for (int i = 0; i < 1 << fs.size(); i++) {
41                 int prod = 1, cnt = 0;    // prod是分母的乘积,cnt是乘了几个数 
42                 for (int j = 0; j < fs.size(); j++) {
43                     if (i >> j & 1) prod *= fs[j], cnt++;
44                 }
45                 // 根据容斥原理的公式,如果分母乘了奇数个数,那么符号是-号,否则是+号 
46                 if (cnt & 1) s -= k / prod;
47                 else s += k / prod;
48             }
49             ret = ret * s % mod;    // 乘法原理 
50         }
51     }
52     printf("%d\n", ret);
53 }
54 
55 int main() {
56     int t;
57     scanf("%d", &t);
58     while (t--) {
59         solve();
60     }
61     
62     return 0;
63 }

  2024-02-28 更新:完善题解与代码。

  与上面的分析一样,每个 $b_i$ 能取的数的数量就是 $1 \sim k$ $(k = \lfloor \frac{m}{a_i} \rfloor)$ 中与 $\frac{a_{i-1}}{a_i}$ 互质的数的数量,最后根据乘法原理把每个 $b_i$ 能取的数的数量全部乘上就是答案。

  而 $1 \sim k$ 中与 $\frac{a_{i-1}}{a_i}$ 互质的数的数量,等价于先求出 $1 \sim k$ 中与 $\frac{a_{i-1}}{a_i}$ 不互质的数的数量,记作 $s$,再令 $k$ 减去 $s$。假设 $\frac{a_{i-1}}{a_i}$ 的不同质因子有 $c$ 个分别是 $p_1, \ldots p_c$,由上面分析知道 $c \leq 9$。那么 $s$ 就是 $1 \sim k$ 中能被 $p_1, \ldots p_c$ 中的至少一个数整除的数的数量。因此就可以用容斥原理来求出 $s$,参考能被整除的数

  另外由于 $a_i \mid a_{i-1}$,因此每个 $a_i$ 都能整除 $a_1$,意味着我们只需分解 $a_1$ 的质因子即可,其他 $a_i$ 的质因子必然被 $a_1$ 的包含。

  AC 代码如下,时间复杂度为 $O(2^9 \cdot 9 \cdot n + \log{m})$

#include <bits/stdc++.h>
using namespace std;

typedef long long LL;

const int N = 2e5 + 10, mod = 998244353;

int a[N];

void solve() {
	int n, m;
	scanf("%d %d", &n, &m);
	for (int i = 1; i <= n; i++) {
		scanf("%d", a + i);
	}
	for (int i = 2; i <= n; i++) {
	    if (a[i - 1] % a[i]) {
	        printf("0\n");
	        return;
	    }
	}
	vector<int> p;
	int t = a[1];
	for (int i = 2; i * i <= t; i++) {
	    if (t % i == 0) {
	        p.push_back(i);
	        while (t % i == 0) {
	            t /= i;
	        }
	    }
	}
	if (t > 1) p.push_back(t);
	int ret = 1;
	for (int i = 2; i <= n; i++) {
	    int k = m / a[i], t = a[i - 1] / a[i];
	    vector<int> q;
	    for (auto &x : p) {
	        if (t % x == 0) q.push_back(x);
	    }
	    int s = 0;
	    for (int j = 1; j < 1 << q.size(); j++) {
	        int t = k, c = 0;
	        for (int k = 0; k < q.size(); k++) {
	            if (j >> k & 1) t /= q[k], c++;
	        }
	        if (c & 1) s = (s + t) % mod;
	        else s = (s - t) % mod;
	    }
	    ret = 1ll * ret * (k - s) % mod;
	}
	printf("%d\n", (ret + mod) % mod);
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
	
	return 0;
}

 

参考资料

  CodeTON Round 3 (Div. 1 + Div. 2) Editorial:https://codeforces.com/blog/entry/108504

  CodeTON Round 3 (Div. 1 + Div. 2, Rated, Prizes!) A - E:https://zhuanlan.zhihu.com/p/581011028

posted @ 2022-11-18 11:42  onlyblues  阅读(46)  评论(4编辑  收藏  举报
Web Analytics