简要题意:
求
∑ i = 1 A ∑ j = 1 B ∑ k = 1 C d ( i j k ) \sum_{i=1}^A \sum_{j=1}^B \sum_{k=1}^C d(ijk) i=1∑Aj=1∑Bk=1∑Cd(ijk)
其中 d ( x ) d(x) d(x) 表示 x x x 的因数个数。
一言不合就推式子!
∑ i = 1 A ∑ j = 1 B ∑ k = 1 C d ( i j k ) \sum_{i=1}^A \sum_{j=1}^B \sum_{k=1}^C d(ijk) i=1∑Aj=1∑Bk=1∑Cd(ijk)
= ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ∑ x = 1 i ∑ y = 1 j ∑ z = 1 k [ gcd ( i , j ) = = 1 ] [ gcd ( i , k ) = = 1 ] [ gcd ( j , k ) = = 1 ] = \sum_{i=1}^A \sum_{j=1}^B \sum_{k=1}^C \sum_{x=1}^i \sum_{y=1}^j \sum_{z=1}^k [\gcd(i,j)==1] [\gcd(i,k)==1] [\gcd(j,k)==1] =i=1∑Aj=1∑Bk=1∑Cx=1∑iy=1∑jz=1∑k[gcd(i,j)==1][gcd(i,k)==1][gcd(j,k)==1]
= ∑ x = 1 A ∑ y = 1 B ∑ z = 1 C [ gcd ( x , y ) = = 1 ] [ gcd ( x , z ) = = 1 ] [ gcd ( y , z ) = = 1 ] ⌊ A x ⌋ ⌊ B y ⌋ ⌊ C z ⌋ = \sum_{x=1}^A \sum_{y=1}^B \sum_{z=1}^C [\gcd(x,y)==1] [\gcd(x,z)==1] [\gcd(y,z)==1] \lfloor \frac{A}{x} \rfloor \lfloor \frac{B}{y} \rfloor \lfloor \frac{C}{z} \rfloor =x=1∑Ay=1∑Bz=1∑C[gcd(x,y)==1][gcd(x,z)==1][gcd(y,z)==1]⌊xA⌋⌊yB⌋⌊zC⌋
= ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C [ gcd ( i , j ) = = 1 ] [ gcd ( i , k ) = = 1 ] [ gcd ( j , k ) = = 1 ] ⌊ A i ⌋ ⌊ B j ⌋ ⌊ C k ⌋ = \sum_{i=1}^A \sum_{j=1}^B \sum_{k=1}^C [\gcd(i,j)==1] [\gcd(i,k)==1] [\gcd(j,k)==1] \lfloor \frac{A}{i} \rfloor \lfloor \frac{B}{j} \rfloor \lfloor \frac{C}{k} \rfloor =i=1∑Aj=1∑Bk=1∑C[gcd(i,j)==1][gcd(i,k)==1][gcd(j,k)==1]⌊iA⌋⌊jB⌋⌊kC⌋
= ∑ i = 1 A ∑ j = 1 B ∑ k = 1 C ⌊ A i ⌋ ⌊ B j ⌋ ⌊ C k ⌋ ∑ u ∣ gcd ( i , j ) μ u ∑ v ∣ gcd ( i , k ) μ v ∑ w ∣ gcd ( j , k ) μ k = \sum_{i=1}^A \sum_{j=1}^B \sum_{k=1}^C \lfloor \frac{A}{i} \rfloor \lfloor \frac{B}{j} \rfloor \lfloor \frac{C}{k} \rfloor \sum_{u| \gcd(i,j)} \mu_u \sum_{v| \gcd(i,k)} \mu_v \sum_{w|\gcd(j,k)} \mu_k =i=1∑Aj=1∑Bk=1∑C⌊iA⌋⌊jB⌋⌊kC⌋u∣gcd(i,j)∑μuv∣gcd(i,k)∑μvw∣gcd(j,k)∑μk
= ∑ u = 1 min ( A , B ) μ u ∑ v = 1 min ( A , C ) μ v ∑ w = 1 min ( B , C ) μ w ∑ gcd ( u , v ) ∣ i A ⌊ A i ⌋ ∑ gcd ( u , w ) ∣ j B ⌊ B j ⌋ ∑ gcd ( v , w ) ∣ k C ⌊ C k ⌋ = \sum_{u=1}^{\min(A,B)} \mu_u \sum_{v=1}^{\min(A,C)} \mu_v \sum_{w=1}^{\min(B,C)} \mu_w \sum_{\gcd(u,v)|i}^A \lfloor \frac{A}{i} \rfloor \sum_{\gcd(u,w)|j}^B \lfloor \frac{B}{j} \rfloor \sum_{\gcd(v,w)|k}^C \lfloor \frac{C}{k} \rfloor =u=1∑min(A,B)μuv=1∑min(A,C)μvw=1∑min(B,C)μwgcd(u,v)∣i∑A⌊iA⌋gcd(u,w)∣j∑B⌊jB⌋gcd(v,w)∣k∑C⌊kC⌋
算法一
我会暴力!
时间复杂度: O ( n 3 ) O(n^3) O(n3). 实际得分: 0 p t 0pt 0pt.
恭喜你,一长串式子白推了
算法二
推式子基本结束了,你会发现,式子长得可怕,这并不是我们 A A A 题的前兆!比方说 二元弱化版 本人也写了 题解,可是弱化版推的最后式子很简单啊!
所以首先我们分析,如果就这个式子枚举, O ( n 3 ) O(n^3) O(n3) 是跑不掉的。因为我们没有消掉一个 ∑ \sum ∑,反而按照 所谓的莫比乌斯反演套路 增加了 ∑ \sum ∑.
令
f y , x = ∑ x ∣ i y ⌊ y i ⌋ f_{y,x} = \sum_{x|i}^y \lfloor \frac{y}{i} \rfloor fy,x=x∣i∑y⌊iy⌋
将原式后面的一长串简化:
∑
u
=
1
min
(
A
,
B
)
μ
u
∑
v
=
1
min
(
A
,
C
)
μ
v
∑
w
=
1
min
(
B
,
C
)
μ
w
∑
gcd
(
u
,
v
)
∣
i
A
⌊
A
i
⌋
∑
gcd
(
u
,
w
)
∣
j
B
⌊
B
j
⌋
∑
gcd
(
v
,
w
)
∣
k
C
⌊
C
k
⌋
\sum_{u=1}^{\min(A,B)} \mu_u \sum_{v=1}^{\min(A,C)} \mu_v \sum_{w=1}^{\min(B,C)} \mu_w \sum_{\gcd(u,v)|i}^A \lfloor \frac{A}{i} \rfloor \sum_{\gcd(u,w)|j}^B \lfloor \frac{B}{j} \rfloor \sum_{\gcd(v,w)|k}^C \lfloor \frac{C}{k} \rfloor
u=1∑min(A,B)μuv=1∑min(A,C)μvw=1∑min(B,C)μwgcd(u,v)∣i∑A⌊iA⌋gcd(u,w)∣j∑B⌊jB⌋gcd(v,w)∣k∑C⌊kC⌋
= ∑ u = 1 min ( A , B ) μ u ∑ v = 1 min ( A , C ) μ v ∑ w = 1 min ( B , C ) μ w f A ( gcd ( u , v ) ) f B ( gcd ( u , w ) ) f C ( gcd ( v , w ) ) = \sum_{u=1}^{\min(A,B)} \mu_u \sum_{v=1}^{\min(A,C)} \mu_v \sum_{w=1}^{\min(B,C)} \mu_w f_A(\gcd(u,v)) f_B(\gcd(u,w)) f_C(\gcd(v,w)) =u=1∑min(A,B)μuv=1∑min(A,C)μvw=1∑min(B,C)μwfA(gcd(u,v))fB(gcd(u,w))fC(gcd(v,w))
这只是看起来简单了,实质上, O ( n log n ) O(n \log n) O(nlogn) 预处理 f f f 可以办到,但是就当前式子,大力枚举还是 O ( n 3 ) O(n^3) O(n3),没有一点部分分可拿。这是令人痛苦的地方。
时间复杂度: O ( n 3 ) O(n^3) O(n3). 实际得分: 0 p t 0pt 0pt.
算法三
越接近答案的推导,就显得越困难。现在我们到了黎明前那个最黑暗的时刻。
我们考虑,什么时候 u , v , w u,v,w u,v,w 对答案没有贡献。
显然, μ u = 0 \mu_u = 0 μu=0 或 μ v = 0 \mu_v=0 μv=0 或 μ w = 0 \mu_w=0 μw=0 都会没有贡献。
而 f y ( x ) = 0 f_y(x) = 0 fy(x)=0,就需要 gcd ( u , v ) > A \gcd(u,v)>A gcd(u,v)>A 或 gcd ( u , w ) > B \gcd(u,w)>B gcd(u,w)>B 或 gcd ( v , w ) > C \gcd(v,w)>C gcd(v,w)>C.
似乎情况还蛮多的?
所以我们考虑感性一点,枚举 gcd = g \gcd=g gcd=g,然后 u = i g , v = j g u=ig , v=jg u=ig,v=jg 合法 当且仅当 gcd ( i , j ) = 1 , μ u × μ v ≠ 0 , lcm u , v = i j g ≤ max ( a , b , c ) \gcd(i,j)=1 , \mu_u \times \mu_v \not = 0 , \operatorname{lcm}{u,v}=ijg \leq \max(a,b,c) gcd(i,j)=1,μu×μv=0,lcmu,v=ijg≤max(a,b,c).
对于合法的 u , v u,v u,v 连边,我们就得到了一张图。
那么合法的情况是怎样的?即 u → v , u → w , v → w u \rightarrow v , u \rightarrow w , v \rightarrow w u→v,u→w,v→w 在原图中同时存在。
即需要求出原图的 三元环个数,可以参考 不常用的黑科技——「三元环」,在 O ( n log n ) O(n \log n) O(nlogn) 的时间求解。
那么, n = ? n = ? n=?,也就是这个图的边数会不会很大呢?
一位叫做 shadowice1984 \text{shadowice1984} shadowice1984 的人告诉我们边数最多只有 760741 760741 760741 条,所以就放心吧!
对于后面的一堆东西用 整除分块 可以实现。
对于 n = 7.5 × 1 0 5 n=7.5 \times 10^5 n=7.5×105,用 n n n \sqrt{n} nn 整除分块 需要格外小心,常数很危险,需要反复卡常才能过 ⋯ ⋯ \cdots \cdots ⋯⋯
本人在卡常
15
15
15 次后
AC
\text{AC}
AC 了本题。。 把几乎同样的代码不断提交
时间复杂度: O ( n n × T ) O(n \sqrt {n} \times T) O(nn×T).
其中 n ≤ 7.5 × 1 0 5 n \leq 7.5 \times 10^5 n≤7.5×105.
期望得分: 100 p t s 100pts 100pts. 实际得分: 70 70 70 ~ 100 p t s 100pts 100pts.(取决于常数)
如果你交我代码发现A不了,只能说你人品差了
// i=-~i 是 i++ 的优化
// 所有 min , max , gcd 手写卡常
// register 寄存器用来优化
// 一段 GCC 优化模板
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#pragma GCC optimize(5000)
#pragma GCC optimize(100000000)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll N=8e5+5,MOD=1e9+7;
inline ll read(){char ch=getchar(); ll f=1;while(ch<'0' || ch>'9') {if(ch=='-') f=-f; ch=getchar();}
ll x=0;while(ch>='0' && ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();return x*f;}
ll a,b,c,T,cnt,tot,ans;
ll lst[N],d[N],p[N],mu[N],ok[N],ord[N],deg[N],f[N],from[N],to[N],lcm[N],mrk[N];
vector<ll>v[N],w[N];
inline ll min(ll a,ll b){return a<b?a:b;}
inline ll max(ll a,ll b){return a>b?a:b;}
inline ll gcd(ll a,ll b){return (!b)?a:gcd(b,a%b);}
int main() {
p[1]=mu[1]=1;
for(register int i=2;i<N;i=-~i) {
if(!p[i]) lst[++cnt]=i,mu[i]=-1;
for(register int j=1;j<=cnt;j=-~j){
if(i*lst[j]>=N) break;
p[i*lst[j]]=1;
if(i%lst[j]==0) {mu[i*lst[j]]=0;break;}
mu[i*lst[j]]=-mu[i];
}
} for(register int i=1;i<N;i=-~i)
if(mu[i]) ok[++tot]=i,ord[i]=tot;
for(register int i=1;i<N;i=-~i) {
for(register int j=1;i*j<N;j=-~j) d[i*j]++;
f[i]=(f[i-1]+d[i])%MOD;
} T=read();
while(T--) {
memset(deg,0,sizeof(deg));
memset(v,0,sizeof(v));
memset(w,0,sizeof(w));
a=read(),b=read(),c=read();
ll mn=min(min(a,b),c),mx=max(max(a,b),c);
ll e=ans=0;
for(register int i=1;i<=tot;i=-~i){
if(ok[i]>mx) break;
for(register int j=1;j<=tot;j=-~j){
if(ok[i]*ok[j]>mx) break;
if(!mu[ok[i]*ok[j]]) continue;
for(register int k=j+1;k<=tot;k=-~k){
if(ok[i]*ok[j]*ok[k]>mx) break;
if(mu[ok[i]*ok[k]]==0||gcd(ok[j],ok[k])>1) continue;
from[++e]=ord[ok[i]*ok[j]],to[e]=ord[ok[i]*ok[k]],lcm[e]=ok[i]*ok[j]*ok[k];
deg[from[e]]++,deg[to[e]]++;
}
}
}
for(register int i=1;i<=tot;i=-~i) {
if(ok[i]>mn) break;
ans+=mu[ok[i]]*mu[ok[i]]*mu[ok[i]]*f[a/ok[i]]*f[b/ok[i]]*f[c/ok[i]];
}
for(register int i=1;i<=e;i=-~i) {
v[from[i]].push_back(to[i]),w[from[i]].push_back(lcm[i]);
v[to[i]].push_back(from[i]),w[to[i]].push_back(lcm[i]);
}
for(register int i=1;i<=tot;i=-~i) {
if(ok[i]>min(a,b)) break;
for(register int j=0;j<v[i].size();j=-~j) {
ll x=ok[i],y=ok[v[i][j]],z=w[i][j];
ans=(ans+mu[x]*mu[y]*mu[y]*f[a/z]*f[b/z]*f[c/y]);
ans=(ans+mu[x]*mu[x]*mu[y]*f[a/x]*f[b/z]*f[c/z]);
ans=(ans+mu[x]*mu[x]*mu[y]*f[a/z]*f[b/x]*f[c/z]);
}
} ans=(ans+MOD)%MOD;
memset(v,0,sizeof(v));
memset(w,0,sizeof(w));
for(register int i=1;i<=e;i=-~i) {
if(deg[from[i]]>=deg[to[i]]) v[from[i]].push_back(to[i]),w[from[i]].push_back(lcm[i]);
else v[to[i]].push_back(from[i]),w[to[i]].push_back(lcm[i]);
}
for(register int i=1;i<=tot;i=-~i) {
if(ok[i]>mx) break;
for(register int j=0;j<v[i].size();j=-~j) mrk[v[i][j]]=w[i][j];
for(register int j=0;j<v[i].size();j=-~j){
ll x=v[i][j];
for(register int k=0;k<v[x].size();k=-~k){
ll y=v[x][k],p=mrk[y],q=w[i][j],r=w[x][k];
if(!mrk[y]) continue;
ll st1,st2,st3,st4,st5,st6;
st1=f[a/p]*f[b/q]*f[c/r];
st2=f[a/p]*f[b/r]*f[c/q];
st3=f[a/q]*f[b/p]*f[c/r];
st4=f[a/q]*f[b/r]*f[c/p];
st5=f[a/r]*f[b/p]*f[c/q];
st6=f[a/r]*f[b/q]*f[c/p];
ans=(ans+mu[ok[i]]*mu[ok[x]]*mu[ok[y]]*(st1+st2+st3+st4+st5+st6)+MOD)%MOD;
}
} for(register int j=0;j<v[i].size();j=-~j) mrk[v[i][j]]=0;
}
printf("%lld\n",(ans+MOD)%MOD);
}
return 0;
}