题目地址

题目链接

Description

 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×10 5. 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

Solution

神仙结论。不过其实不难想。。。但是我不看题解很难想到。
首先大力推式子但是我懒得写推导在这里了意会一下吧,写到这道题应该也不难推到这里=_=
\[ \sum_{T=1}^n\frac{n}{T}\frac{m}{T}\sum_{d|T}\mu(\frac{T}{d})[h(d)<=p] \]
但是这个\(h(d)\)怎么解决真的不知道。。。p是每次给定的啊。。。
于是抄题解,领会到了神仙们的神仙思维多么强大。
\(2^{18}\)就大于\(500000\)了,所以\(h(i)\)一定都小于18,对于p大于18的,表达式一定恒为真,前缀和预处理前p<=18的情况就好了。。

#include <bits/stdc++.h>
using namespace std;

const int N = 500010;
#define ll long long
int mu[N], T, p[N], cnt;
int h[N], sum[20][N], P;
bool vis[N]; 
ll n, m;

void init() {
    mu[1] = 1;
    for(int i = 2; i < N; ++i) {
        if(!vis[i]) p[++cnt] = i, mu[i] = -1, h[i] = 1;
        for(int j = 1; j <= cnt && i * p[j] < N; ++j) {
            vis[i * p[j]] = 1;
            h[i * p[j]] = h[i] + 1;
            if(i % p[j] == 0) break;
            mu[i * p[j]] = -mu[i]; 
        }
    } 
    for(int i = 1; i < N; ++i) 
        for(int j = i; j < N; j += i) 
            sum[h[i]][j] += mu[j / i];
    for(int k = 0; k <= 18; ++k) 
        for(int i = 1; i < N; ++i)
            sum[k][i] += sum[k][i - 1];
    for(int j = 1; j <= 18; ++j) 
        for(int i = 1; i < N; ++i) 
            sum[j][i] += sum[j - 1][i];
}

ll calc(ll n, ll m, ll lim) {
    ll ans = 0;
    if(n > m) swap(n, m);
    for(ll l = 1, r; l <= n; l = r + 1) {
        r = min(n / (n / l), m / (m / l));
        ans += 1ll * (sum[lim][r] - sum[lim][l - 1]) * (n / l) * (m / l);
    }
    return ans;
}

int main() {
    init();
    scanf("%d", &T);
    while(T--) {
        scanf("%lld%lld%d", &n, &m, &P);
        if(P > 18) printf("%lld\n", n * m);
        else printf("%lld\n", calc(n, m, P));
    }
    return 0;
}