CF1750D Count GCD

Problem

多组数据。

每组数据给定两个整数 nm 和一个数列 b,问有多少种方案构造一个长度为 n 的序列 a,满足 1aimgcd(a1,a2,,ai)=bi,答案对 998244353 取模。

Input

第一行输入 t,表示数据组数。

每组数据第一行是两个整数 nm

每组数据第二行输入 n 个整数 b1,b2,,bn

Output

输出 t 行,每行输出一个整数表示答案。

Sample

Input 1

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 1

3
1
0
595458194
200000000

Solution

首先对于 2in,如果 bi1 不是 bi 的倍数,显然无解。

因为 bi=gcd(bi1,ai),所以 gcd(bi1bi,aibi)=1

ai 的取值在 [1,m] 之间,那我们就是需要在 [1,mbi] 中统计出与 bi1bi 互质的数的个数。

考虑容斥,我们令 g 来表示 bi1bi,每次暴力求出 g 的质因子,然后枚举选取质因子的状态,统计答案即可。

由于 bi1bi 的倍数,1bim109,那么如果 bi1bibi1 至少是 bi2 倍,所以说 bi1bi 的情况最多只有 log 次,容斥的次数大幅减少。

而对于 bi1=bi 的情况,g=1,没有质因子,自然就不会容斥来统计答案。

代码:

#include <algorithm>
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std;

const int kmax = 2e5 + 3;
const int Mod = 998244353;

int t, n, m;
int b[kmax];
int p[kmax], pc;
long long res;

long long Calc(int x, int y) { // 容斥
  pc = 0;
  int j = y;
  for (int i = 2; i * i <= y; i++) { // 筛质因子
    if (j % i) continue;
    p[++pc] = i;
    for (; j % i == 0; j /= i) {
    }
  }
  if (j > 1) p[++pc] = j;
  long long res = 0;
  for (int i = 0; i < 1 << pc; i++) { // 枚举状态
    int op = 1;
    long long v = 1;
    for (int j = 0; j < pc; j++) {
      if (i & 1 << j) {
        op *= -1;
        v *= p[j + 1];
      }
    }
    res += op * x / v;
  }
  return res;
}

void Solve() {
  cin >> n >> m;
  for (int i = 1; i <= n; i++) {
    cin >> b[i];
  }
  res = 1;
  for (int i = 2; i <= n; i++) {
    if (b[i - 1] % b[i]) { // 无解
      cout << 0 << '\n';
      return;
    }
    res = res * Calc(m / b[i], b[i - 1] / b[i]) % Mod; // 统计答案
  }
  cout << res << '\n';
}

int main() {
  cin >> t;
  while (t--) {
    Solve();
  }
  return 0;
}
posted @   ereoth  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示