Mophues
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
题意
求
g
c
d
(
a
,
b
)
gcd(a,b)
gcd(a,b)的素因子个数小于
P
P
P的对
(
a
,
b
)
(
1
<
=
a
<
=
n
,
1
<
=
b
<
=
m
)
(a,b)(1<=a<=n,1<=b<=m)
(a,b)(1<=a<=n,1<=b<=m)的个数
题解
莫比乌斯反演。
令
f
(
d
)
f(d)
f(d)表示
g
c
d
(
a
,
b
)
=
d
gcd(a,b)=d
gcd(a,b)=d且
a
,
b
a,b
a,b满足题意的对
(
a
,
b
)
(a,b)
(a,b)的个数,
F
(
d
)
F(d)
F(d)表示满足
d
∣
g
c
d
(
a
,
b
)
d|gcd(a,b)
d∣gcd(a,b)且
a
,
b
a,b
a,b满足题意的对
(
a
,
b
)
(a,b)
(a,b)的个数。
关系式:
F
(
x
)
=
Σ
x
∣
d
f
(
d
)
F(x)=\Sigma_{x|d}f(d)
F(x)=Σx∣df(d)
由
F
(
d
)
F(d)
F(d)显然:
F
(
x
)
=
n
x
∗
m
x
F(x)=\frac{n}{x}*\frac{m}{x}
F(x)=xn∗xm
反演得:
f
(
x
)
=
Σ
x
∣
d
μ
(
d
x
)
∗
F
(
d
)
=
Σ
x
∣
d
μ
(
d
x
)
∗
(
n
d
)
∗
(
m
d
)
f(x)=\Sigma_{x|d}\mu(\frac{d}{x})*F(d)=\Sigma_{x|d}\mu(\frac{d}{x})*(\frac{n}{d})*(\frac{m}{d})
f(x)=Σx∣dμ(xd)∗F(d)=Σx∣dμ(xd)∗(dn)∗(dm)
以第二个样例为例:
s
u
m
=
f
(
1
)
+
f
(
2
)
+
f
(
3
)
+
f
(
5
)
+
f
(
7
)
sum=f(1)+f(2)+f(3)+f(5)+f(7)
sum=f(1)+f(2)+f(3)+f(5)+f(7)
以
F
(
n
)
F(n)
F(n)表示为
s
u
m
=
sum=
sum=
F
(
1
)
[
μ
(
1
)
]
+
F(1)[\mu(1)]+
F(1)[μ(1)]+
F
(
2
)
[
μ
(
1
)
+
μ
(
2
)
]
+
F(2)[\mu(1)+\mu(2)]+
F(2)[μ(1)+μ(2)]+
F
(
3
)
[
μ
(
1
)
+
μ
(
3
)
]
+
F(3)[\mu(1)+\mu(3)]+
F(3)[μ(1)+μ(3)]+
F
(
4
)
[
μ
(
1
)
+
μ
(
2
)
+
μ
(
4
)
]
+
F(4)[\mu(1)+\mu(2)+\mu(4)]+
F(4)[μ(1)+μ(2)+μ(4)]+
F
(
5
)
[
μ
(
1
)
+
μ
(
5
)
]
+
F(5)[\mu(1)+\mu(5)]+
F(5)[μ(1)+μ(5)]+
F
(
6
)
[
μ
(
1
)
+
μ
(
2
)
+
μ
(
3
)
+
μ
(
6
)
]
+
F(6)[\mu(1)+\mu(2)+\mu(3)+\mu(6)]+
F(6)[μ(1)+μ(2)+μ(3)+μ(6)]+
F
(
7
)
[
μ
(
1
)
+
μ
(
7
)
]
+
F(7)[\mu(1)+\mu(7)]+
F(7)[μ(1)+μ(7)]+
F
(
8
)
[
μ
(
1
)
+
μ
(
2
)
+
μ
(
4
)
+
μ
(
8
)
]
+
F(8)[\mu(1)+\mu(2)+\mu(4)+\mu(8)]+
F(8)[μ(1)+μ(2)+μ(4)+μ(8)]+
F
(
9
)
[
μ
(
1
)
+
μ
(
3
)
+
μ
(
9
)
]
+
F(9)[\mu(1)+\mu(3)+\mu(9)]+
F(9)[μ(1)+μ(3)+μ(9)]+
F
(
10
)
[
μ
(
1
)
+
μ
(
2
)
+
μ
(
5
)
+
μ
(
10
)
]
F(10)[\mu(1)+\mu(2)+\mu(5)+\mu(10)]
F(10)[μ(1)+μ(2)+μ(5)+μ(10)]
得:
s
u
m
=
Σ
d
=
1
m
i
n
(
n
,
m
)
(
n
d
)
(
m
d
)
Σ
x
∣
d
μ
(
x
)
sum=\Sigma_{d=1}^{min(n,m)}(\frac{n}{d})(\frac{m}{d})\Sigma_{x|d}\mu(x)
sum=Σd=1min(n,m)(dn)(dm)Σx∣dμ(x)
所以用 n u m [ i ] num[i] num[i]数组存 ( a , b ) (a,b) (a,b)的对数,因为 2 19 = 524288 > 5 e 5 2^{19}=524288>5e5 219=524288>5e5所以素因子个数不会超过19个,数组 n u m num num开为二维数组,令 n u m [ i ] [ j ] num[i][j] num[i][j]表示素因子数量小于等于 j j j个的前 i i i项和
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <queue>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
#include <cmath>
using namespace std;
#define me(x,y) memset(x,y,sizeof x)
#define MIN(x,y) x < y ? x : y
#define MAX(x,y) x > y ? x : y
typedef long long ll;
const int maxn = 5e5;
const double INF = 0x3f3f3f3f;
const int MOD = 1e9+7;
int prime[maxn+10],mu[maxn+10],tot = 0;
int cnt[maxn+10],num[maxn+10][22];
bool vis[maxn+10];
void Mobius(){
me(vis,false);
mu[1] = 1;
for(int i = 2; i <= maxn; ++i){
if(!vis[i]) prime[++tot] = i,mu[i] = -1,cnt[i] = 1;
for(int j = 1; j <= tot & i*prime[j] <= maxn; ++j){
vis[i*prime[j]] = true;
cnt[i*prime[j]] = cnt[i]+1;
if(i%prime[j] == 0){
mu[i*prime[j]] = 0;
break;
}
mu[i*prime[j]] = -mu[i];
}
}
for(int i = 1; i <= maxn; ++i){ //
for(int j = i; j <= maxn; j+=i){
num[j][cnt[i]] += mu[j/i];
}
}
for(int i = 1; i <= maxn; ++i){
for(int j = 0; j <= 20;++j){
num[i][j] += num[i][j-1];
}
}
for(int i = 1; i <= maxn; ++i){
for(int j = 0; j <= 20; ++j){
num[i][j] += num[i-1][j];
}
}
}
int main(){
int t;
cin>>t;
Mobius();
while(t--){
int n,m,p;
scanf("%d%d%d",&n,&m,&p);
if(p > 19) p = 19;
ll sum = 0;
for(int l = 1,r; l <= min(n,m); l = r+ 1){
r = min(n/(n/l),m/(m/l));
sum += (ll)(n/l)*(m/l)*(num[r][p]-num[l-1][p]);
}
printf("%lld\n",sum);
}
return 0;
}
/*
*/