Mophues HDU - 4746
题面
As we know, any positive integer C ( C >= 2 ) can be written as the multiply of some prime numbers:
C = p1×p2× p3× ... × pk
which p1, p2 ... pk are all prime numbers.For example, if C = 24, then:
24 = 2 × 2 × 2 × 3
here, p1 = p2 = p3 = 2, p4 = 3, k = 4
Given two integers P and C. if k<=P( k is the number of C's prime factors), we call C a lucky number of P.
Now, XXX needs to count the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of a given P ( "gcd" means "greatest common divisor").
Please note that we define 1 as lucky number of any non-negative integers because 1 has no prime factor.
Input
The first line of input is an integer Q meaning that there are Q test cases.
Then Q lines follow, each line is a test case and each test case contains three non-negative numbers: n, m and P (n, m, P <= 5×105. Q <=5000).
Output
For each test case, print the number of pairs (a, b), which 1<=a<=n , 1<=b<=m, and gcd(a,b) is a lucky number of P.
Sample Input
2
10 10 0
10 10 1
Sample Output
63
93
题解
直接先裸一下莫比乌斯
\(ans = \sum_{k(k \ prime \ numbers <= p)}^{min(n, m)}\sum_{i}^{n}\sum_{j}^{m} [gcd(i, j) == k]\)
设 f(k) = \(\sum_{i}^{n}\sum_{j}^{m} [gcd(i, j) == k]\)
则 \(ans = \sum_{k(k \ prime \ numbers <= p)}^{min(n, m)}\sum_{i}^{min(n,m) / k} \mu(i) * \left \lfloor \left \lfloor n/k \right \rfloor /i \right \rfloor * \left \lfloor \left \lfloor m/k \right \rfloor /i \right \rfloor\) 然而分块之后是 n * log, 别忘了我们是多个询问
那只好想办法把枚举 k 这一步省了, 变一下 ans
\(ans = \sum_d \left \lfloor n / d \right \rfloor * \left \lfloor m / d \right \rfloor \sum_{k | d} \mu(d/k))\)
我们就省掉了枚举 k, 而是取枚举 d, 左分块, 右预处理
ps: log2(5e5) < 19, 故 p >= 19, 直接 n * m
代码
int miu[N], prime[N], v[N], tot;
ll s[19][N];
void getmiu(int n) {
miu[1] = 1;
rep (i, 2, n) {
if (!v[i]) prime[++tot] = i, miu[i] = -1, v[i] = 1;
for (int j = 1; prime[j] <= n / i && j <= tot; ++j) {
v[prime[j] * i] = v[i] + 1;
if (i % prime[j] == 0) break;
else miu[i * prime[j]] = -miu[i];
}
}
}
void init(int n) {
rep (i, 1, n)
for (int j = i, t = 1; j <= n; j += i, ++t)
s[v[i]][j] += miu[t];
rep (j, 1, n) rep (i, 1, 18) s[i][j] += s[i - 1][j];
rep (j, 1, n) rep (i, 0, 18) s[i][j] += s[i][j - 1];
}
int main() {
IOS; getmiu(5e5); init(5e5);
for (cin >> _; _; --_) {
ll n, m, p, ans = 0; cin >> n >> m >> p;
if (p >= 19) { cout << m * n << '\n'; continue; }
if (n > m) swap(n, m);
for (int i = 1, j; i <= n; i = j + 1) {
j = min(n / (n / i), m / (m / i));
ans += (s[p][j] - s[p][i - 1]) * (n / i) * (m / i);
}
cout << ans << '\n';
}
return 0;
}