题意
A,B,C≤1e7
A
,
B
,
C
≤
1
e
7
题解
很难受 写这题的时候真是又困又难受,冷静下来细想并没有那么难qwq
学计算机果然要身体好才行呀
对于这个东西,我们先想到把
phi
p
h
i
和
gcd
g
c
d
拆开。
设
f(d)
f
(
d
)
表示存在多少个
i,j,k
i
,
j
,
k
使得
d|gcd(i,j2,k3)
d
|
g
c
d
(
i
,
j
2
,
k
3
)
设
g(d)
g
(
d
)
表示存在多少个
i,j,k
i
,
j
,
k
使得
d==gcd(i,j2,k3)
d
==
g
c
d
(
i
,
j
2
,
k
3
)
我们先不考虑怎么求
f,g
f
,
g
那么 ans=∑g(d)∗ϕ(d) a n s = ∑ g ( d ) ∗ ϕ ( d )
容易发现
然后我们莫比乌斯一下
再把这个带入 ans a n s
两个积性函数的狄利克雷卷积还是积性函数,后面这部分可以搞一搞线筛出来。
前面这一部分也好算 f(k)=Ak∗Bb[k]∗Cc[k] f ( k ) = A k ∗ B b [ k ] ∗ C c [ k ]
b[k]为最小的x使得 x∗x%k==0 x ∗ x % k == 0
c[k]同理
然后b[k],c[k]也是积性函数,线筛搞搞就可以了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned int ui;
const int maxn = 1e7 + 10;
const int mod = 1<<30;
int prm[maxn], phi[maxn], tot;
bool ok[maxn];
ui bb[maxn], cc[maxn], sx[maxn], fck[maxn];
void get_prime(int n){
tot = 0;
memset(ok, 0, sizeof(ok)); phi[1] = 1;
cc[1] = bb[1] = 1;
sx[1] = 1;
for (int i = 2; i <= n; i ++){
if (!ok[i]){
prm[++ tot] = i;
phi[i] = i - 1;
cc[i] = bb[i] = i;
sx[i] = i - 2;
fck[i] = i;
}
for (int j = 1; j <= tot; j ++){
if (1LL * i * prm[j] > n) break;
if (1LL * bb[i] * bb[i] % (i * prm[j]) == 0)
bb[i * prm[j]] = bb[i];
else bb[i * prm[j]] = bb[i] * prm[j];
if (1LL * cc[i] * cc[i] % (i * prm[j]) * cc[i] % (i * prm[j]) == 0)
cc[i * prm[j]] = cc[i];
else cc[i * prm[j]] = cc[i] * prm[j];
ok[i * prm[j]] = true;
if (i % prm[j]){
phi[i * prm[j]] = phi[i] * phi[prm[j]];
sx[i * prm[j]] = sx[i] * sx[prm[j]];
fck[i * prm[j]] = prm[j];
}
else{
phi[i * prm[j]] = phi[i] * prm[j];
sx[i * prm[j]] = sx[i / fck[i]] * (phi[fck[i] * prm[j]] - phi[fck[i]]);
fck[i * prm[j]] = fck[i] * prm[j];
break;
}
}
}
}
bool nsp[maxn];
void prepare(){
get_prime(maxn - 1);
}
void work(){
ui A,B,C;
scanf("%u%u%u", &A, &B, &C);
ui qwq = 0;
for (int i = A; i; i --){
qwq = qwq + 1LL * (A / i) * (B / bb[i]) * (C / cc[i]) * sx[i];
}
printf("%u\n", qwq % mod);
}
int main(){
prepare();
int T; scanf("%d", &T);
while (T --)
work();
return 0;
}