D. Count GCD
D. Count GCD
You are given two integers and and an array of integers. For each it holds that .
Your task is to count the number of different arrays of length such that:
- for each , and
- for each .
Here denotes the greatest common divisor (GCD) of integers .
Since this number can be too large, print it modulo .
Input
Each test consist of multiple test cases. The first line contains a single integer () — the number of test cases. The description of test cases follows.
The first line of each test case contains two integers and (, ) — the length of the array and the maximum possible value of the element.
The second line of each test case contains integers () — the elements of the array .
It is guaranteed that the sum of across all test cases doesn't exceed .
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 .
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 are:
- ;
- ;
- .
In the second test case, the only array satisfying the demands is .
In the third test case, it can be proven no such array exists.
解题思路
由于有,因此容易发现。因此如果,那么就一定无解,即满足条件的数组数量为。
否则,由于,因此应该是的倍数,即,其中。同时还需要注意到要满足,即和除去最大公因子后,应该与互质,否则最大公因子就不是了。因此选择的还应该满足不能含有的任何一个质因子,即满足。这个就可以用容斥原理来实现。
因此需要先对分解质因子,由于在不超过的数中分解得到不同的质因子的个数最多不超过个(),因此为了实现方便这里容斥原理可以通过二进制枚举的方式来实现。
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 更新:完善题解与代码。
与上面的分析一样,每个 能取的数的数量就是 中与 互质的数的数量,最后根据乘法原理把每个 能取的数的数量全部乘上就是答案。
而 中与 互质的数的数量,等价于先求出 中与 不互质的数的数量,记作 ,再令 减去 。假设 的不同质因子有 个分别是 ,由上面分析知道 。那么 就是 中能被 中的至少一个数整除的数的数量。因此就可以用容斥原理来求出 ,参考能被整除的数。
另外由于 ,因此每个 都能整除 ,意味着我们只需分解 的质因子即可,其他 的质因子必然被 的包含。
AC 代码如下,时间复杂度为
#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
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16902713.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效