Description
对于正整数n,定义
f
(
n
)
f(n)
f(n) 为
n
n
n 所含质因子的最大幂指数。例如
f
(
1960
)
=
f
(
2
3
∗
5
1
∗
7
2
)
=
3
,
f
(
10007
)
=
1
,
f
(
1
)
=
0
f(1960)=f(2^3 * 5^1 * 7^2)=3, f(10007)=1, f(1)=0
f(1960)=f(23∗51∗72)=3,f(10007)=1,f(1)=0。
给定正整数a,b,求
∑
i
=
1
n
∑
j
=
1
m
f
(
g
c
d
(
i
,
j
)
)
\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))
∑i=1n∑j=1mf(gcd(i,j))。
Input
第一行一个数T,表示询问数。
接下来T行,每行两个数a,b,表示一个询问。
Output
对于每一个询问,输出一行一个非负整数作为回答。
Sample Input
4
7558588 9653114
6514903 4451211
7425644 1189442
6335198 4957
Sample Output
35793453939901
14225956593420
4332838845846
15400094813
HINT
【数据规模】
T<=10000
1<=a,b<=10^7
分析:
推一波式子可得,
∑
i
=
1
n
∑
j
=
1
m
f
(
g
c
d
(
i
,
j
)
)
\sum_{i=1}^{n}\sum_{j=1}^{m}f(gcd(i,j))
i=1∑nj=1∑mf(gcd(i,j))
∑
D
=
1
n
f
(
D
)
∑
i
=
1
⌊
n
D
⌋
μ
(
d
)
∗
⌊
n
D
d
⌋
∗
⌊
m
D
d
⌋
\sum_{D=1}^{n}f(D)\sum_{i=1}^{\lfloor\frac{n}{D}\rfloor}\mu(d)*\lfloor\frac{n}{Dd}\rfloor*\lfloor\frac{m}{Dd}\rfloor
D=1∑nf(D)i=1∑⌊Dn⌋μ(d)∗⌊Ddn⌋∗⌊Ddm⌋
∑
T
=
1
n
⌊
n
T
⌋
⌊
m
T
⌋
∑
d
∣
T
μ
(
d
)
∗
f
(
T
d
)
\sum_{T=1}^{n}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d|T}\mu(d)*f(\frac{T}{d})
T=1∑n⌊Tn⌋⌊Tm⌋d∣T∑μ(d)∗f(dT)
现在就是求后面那个东西的前缀和。
设
g
(
T
)
=
∑
d
∣
T
μ
(
d
)
∗
f
(
T
d
)
g(T)=\sum_{d|T}\mu(d)*f(\frac{T}{d})
g(T)=∑d∣Tμ(d)∗f(dT),
因为要想
μ
(
d
)
\mu(d)
μ(d)不为
0
0
0,满足
d
=
p
1
α
1
∗
p
2
α
2
∗
.
.
.
.
∗
p
k
α
k
d=p_1^{\alpha_1}*p_2^{\alpha_2}*....*p_k^{\alpha_k}
d=p1α1∗p2α2∗....∗pkαk
其中
α
i
=
[
0
,
1
]
\alpha_i=[0,1]
αi=[0,1]。
考虑对于一个
T
T
T,他的幂次只有减
1
1
1或不变。也就是说,一开始最大的数,改变后还是最大的。
我们把
α
i
\alpha_i
αi分成两类,
A
A
A为最大的数(包括和他一样的),
B
B
B为不是最大的数。
组合数知识可以知道,在
B
B
B中选出奇数个和偶数个的方案数是一样的,除非
B
B
B为空集。
假设
B
B
B不为空,此时无论
A
A
A如何选,
B
B
B中奇偶数一样,而贡献正好相反,所以总贡献为
0
0
0。
如果
B
B
B为空,说明
A
A
A全是同一个数,除非全选最大值才会变。如果不变恰好为
0
0
0,所以减了
1
1
1贡献为
−
(
−
1
)
k
-(-1)^k
−(−1)k,
k
k
k为质数个数。
考虑怎样求这个东西。我们先找到所有无平方因子数,然后枚举他的幂,枚举幂其实复杂度是很小的,可以看做线性。
代码:
/**************************************************************
Problem: 3309
User: liangzihao
Language: C++
Result: Accepted
Time:17588 ms
Memory:313792 kb
****************************************************************/
#include <iostream>
#include <cstdio>
#include <cmath>
#define LL long long
const int maxn=1e7+7;
using namespace std;
LL T,a,b,n,m,ans,cnt;
LL prime[maxn],not_prime[maxn],mu[maxn],f[maxn];
void get(LL n)
{
mu[1]=1;
for (LL i=2;i<=n;i++)
{
if (!not_prime[i])
{
prime[++cnt]=i;
mu[i]=-1;
}
for (LL j=1;j<=cnt;j++)
{
if (prime[j]*i>n) break;
not_prime[i*prime[j]]=1;
if (i%prime[j]==0)
{
mu[i*prime[j]]=0;
break;
}
mu[i*prime[j]]=-mu[i];
}
}
f[1]=0;
for (LL i=2;i<=n;i++)
{
if (mu[i])
{
for (LL j=i;j<=n;j=j*i)
{
f[j]=-mu[i];
}
}
}
for (LL i=1;i<=n;i++) f[i]+=f[i-1];
}
int main()
{
scanf("%lld",&T);
get(1e7);
while (T--)
{
scanf("%lld%lld",&n,&m);
if (n>m) swap(n,m);
ans=0;
for (LL i=1,last;i<=n;i=last+1)
{
last=min(n/(n/i),m/(m/i));
ans+=(n/i)*(m/i)*(f[last]-f[i-1]);
}
printf("%lld\n",ans);
}
}