2s512M。
解:先分解质因数。考虑按照质因数大小是否大于√分类。
大于的就是一个数颜色个数,莫队即可n√m。
小于的直接枚举质因数做前缀和然后O(1)查询。总时间复杂度n(√m + σ(√V))。
发现我们T飞了,发现莫队的复杂度较优,而处理小于√V的质因数较劣。我们平衡一下。
把界调整到1000。这样比lm大的至多两个,莫队常数*2。而后半部分的复杂度就变成了nσ(3√V),可以通过本题。
1 #include <bits/stdc++.h> 2 3 const int N = 100010, MO = 19260817; 4 5 inline char gc() { 6 static char *p1, *p2, s[N]; 7 if(p1 == p2) p2 = (p1 = s) + fread(s, 1, N, stdin); 8 return (p1 == p2) ? EOF : *p1++; 9 } 10 11 template <class T> inline void read(T &x) { 12 x = 0; 13 register char c(gc()); 14 while(c < '0' || c > '9') { 15 c = gc(); 16 } 17 while(c >= '0' && c <= '9') { 18 x = x * 10 + c - 48; 19 c = gc(); 20 } 21 return; 22 } 23 24 int ex[N], p[N], a[N], lc[N], rc[N], fr[N], top, X[N * 2], xx, inv[N], bin[N], Ans, ans[N], sum[N], exx[N]; 25 bool vis[N]; 26 std::vector<int> v[N], v2[N]; 27 28 struct Node { 29 int l, r, id; 30 inline bool operator < (const Node &w) const { 31 if(fr[l] != fr[w.l]) return l < w.l; 32 return r < w.r; 33 } 34 }node[N]; 35 36 inline void getp(int n) { 37 for(register int i = 2; i <= n; i++) { 38 if(!vis[i]) p[++top] = i; 39 for(int j = 1; j <= top && i * p[j] <= n; j++) { 40 vis[i * p[j]] = 1; 41 if(i % p[j] == 0) break; 42 } 43 } 44 return; 45 } 46 47 inline void add(int y) { 48 if(ex[y]) { 49 int x(ex[y]); 50 if(bin[x]) { 51 Ans = 1ll * Ans * inv[bin[x] + 1] % MO; 52 } 53 ++bin[x]; 54 Ans = 1ll * Ans * (bin[x] + 1) % MO; 55 } 56 if(exx[y]) { 57 int x(exx[y]); 58 if(bin[x]) { 59 Ans = 1ll * Ans * inv[bin[x] + 1] % MO; 60 } 61 ++bin[x]; 62 Ans = 1ll * Ans * (bin[x] + 1) % MO; 63 } 64 return; 65 } 66 67 inline void del(int y) { 68 if(ex[y]) { 69 int x(ex[y]); 70 Ans = 1ll * Ans * inv[bin[x] + 1] % MO; 71 --bin[x]; 72 if(bin[x]) { 73 Ans = 1ll * Ans * (bin[x] + 1) % MO; 74 } 75 } 76 if(exx[y]) { 77 int x(exx[y]); 78 Ans = 1ll * Ans * inv[bin[x] + 1] % MO; 79 --bin[x]; 80 if(bin[x]) { 81 Ans = 1ll * Ans * (bin[x] + 1) % MO; 82 } 83 } 84 return; 85 } 86 87 inline void solve(int x) { 88 printf("div : %d ", x); 89 for(int i = 1; i <= top; i++) { 90 if(x % p[i]) continue; 91 while(x % p[i] == 0) { 92 printf("%d ", p[i]); 93 x /= p[i]; 94 } 95 } 96 if(x > 1) printf("%d ", x); 97 puts(""); 98 return; 99 } 100 101 int main() { 102 getp(31623); 103 104 register int n, m, lm(1000); 105 //scanf("%d%d", &n, &m); 106 read(n), read(m); 107 int T = n / sqrt(m); 108 for(register int i(1); i <= n; ++i) { 109 //scanf("%d", &a[i]); 110 read(a[i]); 111 fr[i] = (i - 1) / T + 1; 112 register int x(a[i]), j(1); 113 for(; p[j] <= lm && p[j] <= x; ++j) { 114 register int cnt(0); 115 while(x % p[j] == 0) { 116 x /= p[j]; 117 ++cnt; 118 } 119 if(cnt) { 120 v[j].push_back(i); 121 v2[j].push_back(cnt); 122 } 123 } 124 if(x == 1) continue; 125 for(; j <= top; j++) { 126 if(x % p[j] == 0) { 127 exx[i] = p[j]; 128 X[++xx] = p[j]; 129 x /= p[j]; 130 break; 131 } 132 } 133 if(x > 1) { 134 ex[i] = x; 135 X[++xx] = x; 136 } 137 } 138 139 std::sort(X + 1, X + xx + 1); 140 xx = std::unique(X + 1, X + xx + 1) - X - 1; 141 for(register int i(1); i <= n; ++i) { 142 //printf("i = %d : %d %d ", i, ex[i], exx[i]); 143 if(ex[i]) { 144 ex[i] = std::lower_bound(X + 1, X + xx + 1, ex[i]) - X; 145 } 146 if(exx[i]) { 147 exx[i] = std::lower_bound(X + 1, X + xx + 1, exx[i]) - X; 148 } 149 } 150 151 for(register int i(1); i <= m; ++i) { 152 //scanf("%d%d", &node[i].l, &node[i].r); 153 read(node[i].l); read(node[i].r); 154 node[i].id = i; 155 } 156 inv[0] = inv[1] = 1; 157 for(register int i(2); i <= n + 1; ++i) { 158 inv[i] = 1ll * inv[MO % i] * (MO - MO / i) % MO; 159 } 160 161 for(register int i(1); i <= fr[n]; ++i) { 162 lc[i] = rc[i - 1] + 1; 163 rc[i] = lc[i] + T - 1; 164 if(i == fr[n]) rc[i] = n; 165 } 166 167 std::sort(node + 1, node + m + 1); 168 169 Ans = 1; 170 add(1); 171 int l = 1, r = 1; 172 for(register int i = 1; i <= m; i++) { 173 while(r < node[i].r) { 174 add(++r); 175 } 176 while(node[i].l < l) { 177 add(--l); 178 } 179 while(node[i].r < r) { 180 del(r--); 181 } 182 while(l < node[i].l) { 183 del(l++); 184 } 185 ans[node[i].id] = Ans; 186 //printf("ans %d = %d ", node[i].id, Ans); 187 } 188 189 /// step 2 190 191 for(register int i(1); p[i] <= lm; ++i) { 192 int LEN(v[i].size()), p(0); 193 for(register int j(1); j <= n; ++j) { 194 sum[j] = sum[j - 1]; 195 if(p < LEN && v[i][p] == j) { 196 sum[j] += v2[i][p++]; 197 } 198 } 199 for(register int j(1); j <= m; ++j) { 200 int x = sum[node[j].r] - sum[node[j].l - 1]; 201 ans[node[j].id] = 1ll * ans[node[j].id] * (x + 1) % MO; 202 } 203 } 204 205 for(register int i(1); i <= m; ++i) { 206 printf("%d ", ans[i]); 207 } 208 209 return 0; 210 }