SP22382 题解
首先发现
先对
设
然后对于所有
最后用前缀和处理一下,即可做到
那么每次查询的答案即为
代码:
#include <bits/stdc++.h>
using namespace std;
int read() {
int s = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9')
f = (ch == '-' ? -1 : 1), ch = getchar();
while (ch >= '0' && ch <= '9')
s = (s << 1) + (s << 3) + (ch ^ 48), ch = getchar();
return s * f;
}
bool p[1000005];
int pr[1000000], tot = 0;
int ls[1000005], phi[1000005], ans[1000005][25] = {{0}};
bool f[1000005][25] = {{0}};
void szs(int n) {
memset(p, true, sizeof p);
p[0] = p[1] = false;
for (int i = 2; i <= n; i++) {
if (p[i])
pr[++tot] = i, ls[i] = i;
for (int j = 1; j <= tot && i * pr[j] <= n; j++) {
p[i * pr[j]] = false, ls[i * pr[j]] = pr[j];
if (i % pr[j] == 0)
break;
}
}
}
int Phi(int x) {
int z[15], tot = 0, ans = x;
while (x != 1) {
int k = ls[x];
if (z[tot] != k)
z[++tot] = k;
x /= k;
}
for (int i = 1; i <= tot; i++)
ans = ans / z[i] * (z[i] - 1);
return ans;
}
int main() {
szs(1000000);
for (int i = 1; i <= 1000000; i++)
phi[i] = Phi(i);
ans[1][0] = 1, f[1][0] = true;
for (int i = 2; i <= 1000000; i++)
for (int j = 0; j <= 20; j++)
ans[i][j] = ans[i - 1][j] + (f[i][j] = f[phi[i]][j - 1]);
int T = read();
while (T--) {
int l = read(), r = read(), k = read();
printf("%lld\n", ans[r][k] - ans[l - 1][k]);
}
return 0;
}