A - 口算训练
题意:询问 $[L, R]$区间内 的所有数的乘积是否是D的倍数
思路:考虑分解质因数
显然,一个数$x > \sqrt{x} 的质因子只有一个$
那么我们考虑将小于$\sqrt {x}$ 的质因子用线段树维护
其他质因子用vector 维护存在性
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 #define N 100010 5 #define block 317 6 vector <int> fac[N], bigfac[10010]; 7 int t, n, q; 8 int arr[N], pos[N], cnt; 9 10 void init() 11 { 12 cnt = 0; 13 memset(pos, 0, sizeof pos); 14 for (int i = 2; i < N; ++i) 15 { 16 if (pos[i] || i > block) continue; 17 for (int j = i * i; j < N; j += i) 18 pos[j] = 1; 19 } 20 for (int i = 2; i < N; ++i) if (!pos[i]) pos[i] = ++cnt; 21 for (int i = 2; i <= 100000; ++i) 22 { 23 int n = i; 24 for (int j = 2; j * j <= n; ++j) 25 { 26 while (n % j == 0) 27 { 28 n = n / j; 29 fac[i].push_back(j); 30 } 31 } 32 if (n != 1) fac[i].push_back(n); 33 sort(fac[i].begin(), fac[i].end()); 34 } 35 } 36 37 int T[80]; 38 struct SEG 39 { 40 #define M N * 300 41 int a[M], lson[M], rson[M], cnt; 42 void init() { cnt = 0; } 43 void pushup(int id) { a[id] = a[lson[id]] + a[rson[id]]; } 44 void update(int &id, int l, int r, int pos) 45 { 46 if (!id) 47 { 48 id = ++cnt; 49 a[id] = lson[id] = rson[id] = 0; 50 } 51 if (l == r) 52 { 53 ++a[id]; 54 return; 55 } 56 int mid = (l + r) >> 1; 57 if (pos <= mid) update(lson[id], l, mid, pos); 58 else update(rson[id], mid + 1, r, pos); 59 pushup(id); 60 } 61 int query(int id, int l, int r, int ql, int qr) 62 { 63 if (!id) return 0; 64 if (l >= ql && r <= qr) return a[id]; 65 int mid = (l + r) >> 1; 66 int res = 0; 67 if (ql <= mid) res += query(lson[id], l, mid, ql, qr); 68 if (qr > mid) res += query(rson[id], mid + 1, r, ql, qr); 69 return res; 70 } 71 }seg; 72 73 bool Get(int base, int need, int l, int r) 74 { 75 // printf("%d %d %d %d\n", base, need, l, r); 76 int have = 0; 77 if (base < block) 78 { 79 have = seg.query(T[pos[base]], 1, n, l, r); 80 if (have < need) return false; 81 } 82 else 83 { 84 have = upper_bound(bigfac[pos[base]].begin(), bigfac[pos[base]].end(), r) - lower_bound(bigfac[pos[base]].begin(), bigfac[pos[base]].end(), l); 85 if (have < need) return false; 86 } 87 return true; 88 } 89 90 bool work(int l, int r, int d) 91 { 92 if (d == 1) return true; 93 int base = fac[d][0], need = 1, have = 0; 94 for (int i = 1, len = fac[d].size(); i < len; ++i) 95 { 96 if (fac[d][i] != base) 97 { 98 if (Get(base, need, l, r) == false) return false; 99 base = fac[d][i]; 100 need = 1; 101 } 102 else ++need; 103 } 104 return Get(base, need, l, r); 105 } 106 107 int main() 108 { 109 init(); 110 scanf("%d", &t); 111 while (t--) 112 { 113 scanf("%d%d", &n, &q); 114 for (int i = 1; i < 10010; ++i) bigfac[i].clear(); 115 for (int i = 1; i <= n; ++i) scanf("%d", arr + i); 116 seg.init(); memset(T, 0, sizeof T); 117 for (int i = 1; i <= n; ++i) 118 { 119 for (auto it : fac[arr[i]]) 120 { 121 if (it < block) 122 seg.update(T[pos[it]], 1, n, i); 123 else 124 bigfac[pos[it]].push_back(i); 125 } 126 } 127 for (int i = 1; i <= cnt; ++i) sort(bigfac[i].begin(), bigfac[i].end()); 128 for (int i = 1, l, r, d; i <= q; ++i) 129 { 130 scanf("%d%d%d", &l, &r, &d); 131 puts(work(l, r, d) ? "Yes" : "No"); 132 } 133 } 134 return 0; 135 }