zxyoi做这道题的心路历程大概是这样子的:
闲来无事题库乱逛,一搜”约数“出来一道黑题。
然后随手就点开了。
一看这个式子。。。我。。。
好的肯定是要化成两两的 g c d gcd gcd不然没法做。
日,这个怎么化。。。
这个 g c d ( i , j , k ) gcd(i,j,k) gcd(i,j,k)是要干什么?
这个 g c d ( i j , j k , i k ) gcd(ij,jk,ik) gcd(ij,jk,ik)又是什么东西?好像可以用质因数分解来搞一搞。
然后就做出来了。日,这有黑题难度?
一发A了,一看全NM开O2跑得贼快。不行我也要开O2。
然后就洛谷Rank1了。。。
最难受的就是那个 g c d ( i j , j k , i k ) gcd(ij,jk,ik) gcd(ij,jk,ik),所以我们想办法把它给化简。
由于 g c d gcd gcd有一种表示方式是酱紫的:
a = ∏ p i a i , b = ∏ p i b i a=\prod p_i^{a_i},b=\prod p_i^{b_i} a=∏piai,b=∏pibi
则 g c d ( a , b ) = ∏ p i min ( a i , b i ) gcd(a,b)=\prod p_i^{\min(a_i,b_i)} gcd(a,b)=∏pimin(ai,bi)
所以我们考虑分别每个质因子在 i , j , k i,j,k i,j,k中出现的次数,记为 I , J , K I,J,K I,J,K
假设现在考虑且仅考虑质因子 p p p
现在我们考虑给 g c d gcd gcd换一种表示方式,记录当前质因子的次数。
大概就是这么个意思:
g c d ( i , j ) = min ( I , J ) g c d ( j , k ) = min ( J , K ) g c d ( i , k ) = min ( I , K ) g c d ( i , j , k ) = min ( I , J , K ) g c d ( i j , i k , j k ) = min ( I + J , J + K , I + K ) \begin{aligned} gcd(i,j)&=\min(I,J)\\ gcd(j,k)&=\min(J,K)\\ gcd(i,k)&=\min(I,K)\\ gcd(i,j,k)&=\min(I,J,K)\\ gcd(ij,ik,jk)&=\min(I+J,J+K,I+K) \end{aligned} gcd(i,j)gcd(j,k)gcd(i,k)gcd(i,j,k)gcd(ij,ik,jk)=min(I,J)=min(J,K)=min(I,K)=min(I,J,K)=min(I+J,J+K,I+K)
所以 g c d ( i j , i k , j k ) gcd(ij,ik,jk) gcd(ij,ik,jk)就是选择了 I , J , K I,J,K I,J,K三者中较小的两个。
容斥一下可以得到(本质是 M i n − M a x Min-Max Min−Max容斥): min ( I + J , J + K , I + K ) = min ( I , J ) + min ( J , K ) + min ( I , K ) − min ( I , J , K ) \min(I+J,J+K,I+K)=\min(I,J)+\min(J,K)+\min(I,K)-\min(I,J,K) min(I+J,J+K,I+K)=min(I,J)+min(J,K)+min(I,K)−min(I,J,K)
很简单的容斥,就是说,在前三项中,次小值会出现一次,最小值会出现两次,最后一项会删掉重复出现的最小值,所以两边是相等的。
换回 g c d gcd gcd的表达式的话就是这个:
g c d ( i j , i k , j k ) = g c d ( i , j ) g c d ( i , k ) g c d ( j , k ) g c d ( i , j , k ) gcd(ij,ik,jk)=\frac{gcd(i,j)gcd(i,k)gcd(j,k)}{gcd(i,j,k)} gcd(ij,ik,jk)=gcd(i,j,k)gcd(i,j)gcd(i,k)gcd(j,k)
代回去得到我们真正要求的东西:
A n s = ∑ i = 1 n ∑ j = 1 m ∑ k = 1 p g c d ( i , j ) 2 + g c d ( i , k ) 2 + g c d ( j , k ) 2 Ans=\sum_{i=1}^n\sum_{j=1}^m\sum_{k=1}^{p}gcd(i,j)^2+gcd(i,k)^2+gcd(j,k)^2 Ans=i=1∑nj=1∑mk=1∑pgcd(i,j)2+gcd(i,k)2+gcd(j,k)2
然后,zxyoi当场就来了一句 w o c woc woc,这不就是基础莫比乌斯反演题了吗?
考虑将询问拆分一下: A n s = p ∑ i = 1 n ∑ j = 1 m g c d ( i , j ) 2 + n ∑ j = 1 m ∑ k = 1 p g c d ( j , k ) 2 + m ∑ i = 1 n ∑ k = 1 p g c d ( i , k ) 2 Ans=p\sum_{i=1}^{n}\sum_{j=1}^mgcd(i,j)^2+n\sum_{j=1}^m\sum_{k=1}^pgcd(j,k)^2+m\sum_{i=1}^n\sum_{k=1}^pgcd(i,k)^2 Ans=p∑i=1n∑j=1mgcd(i,j)2+n∑j=1m∑k=1pgcd(j,k)2+m∑i=1n∑k=1pgcd(i,k)2
现在考虑怎么处理这个东西:
∑ i = 1 n ∑ j = 1 m g c d ( i , j ) 2 \begin{aligned} \sum_{i=1}^n\sum_{j=1}^mgcd(i,j)^2 \end{aligned} i=1∑nj=1∑mgcd(i,j)2
接下来是莫比乌斯反演的时间:
A n s = ∑ d = 1 min ( n , m ) d 2 ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = d ] = ∑ d = 1 min ( n , m ) d 2 ∑ i = 1 n ∑ j = 1 m ∑ t ∣ g c d ( i , j ) μ ( t ) = ∑ d = 1 min ( n , m ) d 2 ∑ t = 1 ⌊ min ( n , m ) d ⌋ ⌊ n d t ⌋ ⌊ m d t ⌋ = ∑ T = 1 min ( n , m ) ⌊ n T ⌋ ⌊ m T ⌋ ∑ d ∣ T d 2 μ ( T d ) \begin{aligned} Ans=&\sum_{d=1}^{\min(n,m)}d^2\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=d]\\ =&\sum_{d=1}^{\min(n,m)}d^2\sum_{i=1}^n\sum_{j=1}^{m}\sum_{t\mid gcd(i,j)}\mu(t)\\ =&\sum_{d=1}^{\min(n,m)}d^2\sum_{t=1}^{\lfloor\frac{\min(n,m)}{d}\rfloor}\lfloor\frac{n}{dt}\rfloor\lfloor\frac{m}{dt}\rfloor\\ =&\sum_{T=1}^{\min(n,m)}\lfloor\frac{n}{T}\rfloor\lfloor\frac{m}{T}\rfloor\sum_{d\mid T}d^2\mu(\frac{T}d) \end{aligned} Ans====d=1∑min(n,m)d2i=1∑nj=1∑m[gcd(i,j)=d]d=1∑min(n,m)d2i=1∑nj=1∑mt∣gcd(i,j)∑μ(t)d=1∑min(n,m)d2t=1∑⌊dmin(n,m)⌋⌊dtn⌋⌊dtm⌋T=1∑min(n,m)⌊Tn⌋⌊Tm⌋d∣T∑d2μ(dT)
设 g ( T ) = ∑ d ∣ T d 2 μ ( T d ) g(T)=\sum_{d\mid T}d^2\mu(\frac{T}d) g(T)=∑d∣Td2μ(dT)
很显然 g g g是个积性函数,因为 g = I d 2 ∗ μ g=Id^2*\mu g=Id2∗μ
那么考虑线性筛。
g ( 1 ) = 1 g(1)=1 g(1)=1
∀ p ∈ P , g ( p ) = p 2 − 1 \forall p\in \mathbb P,g(p)=p^2-1 ∀p∈P,g(p)=p2−1
∀ p ∈ P , n ∈ N ∗ , g c d ( n , p ) = 1 , g ( n p ) = g ( n ) g ( p ) \forall p\in \mathbb P,n\in \mathbb N_*,gcd(n,p)=1,g(np)=g(n)g(p) ∀p∈P,n∈N∗,gcd(n,p)=1,g(np)=g(n)g(p)
∀ p ∈ P , n ∈ N ∗ , p ∣ n , g ( n p ) = p 2 g ( n ) \forall p\in \mathbb P,n\in \mathbb N_*,p\mid n,g(np)=p^2g(n) ∀p∈P,n∈N∗,p∣n,g(np)=p2g(n)
最后一个稍微考虑一下有哪些数会产生新的贡献大概就明白了。
总的来说感觉不够当一道黑题,顶多紫题。
代码:
#include
using namespace std;
#define ll long long
#define re register
#define gc get_char
#define pc putchar
#define cs const
namespace IO{
namespace IOONLY{
cs int Rlen=1<<16|1;
char buf[Rlen],*p1,*p2;
}
inline char get_char(){
using namespace IOONLY;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
cs int P=20000007,N=P-7;
cs int mod=1000000007;
inline int add(int a,int b){return a+b>=mod?a+b-mod:a+b;}
inline int mul(int a,int b){return (ll)a*b>=mod?(ll)a*b%mod:(ll)a*b;}
inline int dec(int a,int b){return a<b?a-b+mod:a-b;}
int prime[P],pcnt;
int g[P];
bool mark[P];
inline void linear_sieves(int len=N){
g[1]=1;
for(int re i=2;i<=len;++i){
if(!mark[i])prime[++pcnt]=i,g[i]=dec(mul(i,i),1);
for(int re j=1;i*prime[j]<=len;++j){
mark[i*prime[j]]=true;
if(i%prime[j]==0){
g[i*prime[j]]=mul(mul(prime[j],prime[j]),g[i]);
break;
}
g[i*prime[j]]=mul(g[i],g[prime[j]]);
}
}
for(int re i=2;i<=len;++i)g[i]=add(g[i],g[i-1]);
}
inline int calc(int n,int m){
int ans=0;
if(n>m)swap(n,m);
for(int re i=1,j;i<=n;i=j+1){
j=min(n/(n/i),m/(m/i));
ans=add(ans,mul(mul(n/i,m/i),dec(g[j],g[i-1])));
}
return ans;
}
inline int solve(int n,int m,int p){
return add(add(mul(p,calc(n,m)),mul(n,calc(p,m))),mul(m,calc(n,p)));
}
signed main(){
linear_sieves();
for(int re T=getint();T--;cout<<solve(getint(),getint(),getint())<<'\n');
return 0;
}