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;
}

posted @ 2020-10-18 16:29  洛绫璃  阅读(112)  评论(0编辑  收藏  举报