Codeforces 235 E Number Challenge 题解(Mobius反演)

题目:CF 235 E.
题目大意:给定 a , b , c a,b,c a,b,c,设 d ( n ) = ∑ d ∣ n 1 d(n)=\sum_{d|n}1 d(n)=dn1,求 ∑ 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=1aj=1bk=1cd(ijk).
1 ≤ a , b , c ≤ 2000 1\leq a,b,c\leq 2000 1a,b,c2000.

我们考虑SDOI2015 约数个数和中的那个性质:
d ( a b ) = ∑ i ∣ a ∑ j ∣ b [ g c d ( i , j ) = 1 ] d(ab)=\sum_{i|a}\sum_{j|b}[gcd(i,j)=1] d(ab)=iajb[gcd(i,j)=1]

考虑现在我们有的这个式子:
d ( a b c ) = d ( a ∗ b c ) = ∑ i ∣ a ∑ j ∣ b c [ g c d ( i , j ) = 1 ] = ∑ i ∣ a ∑ j ∣ b ∑ k ∣ c [ g c d ( i , j ) = g c d ( i , k ) = g c d ( j , k ) = 1 ] = ̸ ∑ i ∣ a ∑ j ∣ b ∑ k ∣ c [ g c d ( i , j , k ) = 1 ] d(abc)=d(a*bc)\\ =\sum_{i|a}\sum_{j|bc}[gcd(i,j)=1]\\ =\sum_{i|a}\sum_{j|b}\sum_{k|c}[gcd(i,j)=gcd(i,k)=gcd(j,k)=1]\\ =\not{} \sum_{i|a}\sum_{j|b} \sum_{k|c}[gcd(i,j,k)=1] d(abc)=d(abc)=iajbc[gcd(i,j)=1]=iajbkc[gcd(i,j)=gcd(i,k)=gcd(j,k)=1]≠iajbkc[gcd(i,j,k)=1]

注意后面的不等于!!!

有了上面的等式,我们可以开始推导:
∑ i = 1 a ∑ j = 1 b ∑ k = 1 c d ( i j k ) = ∑ i = 1 a ∑ j = 1 b ∑ k = 1 c ∑ x ∣ i ∑ y ∣ j ∑ z ∣ k [ g c d ( x , y ) = g c d ( x , z ) = g c d ( y , z ) = 1 ] = ∑ x = 1 a ∑ y = 1 b ∑ z = 1 c ⌊ a x ⌋ ⌊ b y ⌋ ⌊ c z ⌋ [ g c d ( x , y ) = 1 ] [ g c d ( x , z ) = 1 ] [ g c d ( y , z ) = 1 ] = ∑ x = 1 a ∑ y = 1 b ∑ z = 1 c ⌊ a x ⌋ ⌊ b y ⌋ ⌊ c z ⌋ ∑ t ∣ x ∧ t ∣ y μ ( t ) [ g c d ( x , z ) = 1 ] [ g c d ( y , z ) = 1 ] = ∑ z = 1 c ⌊ c z ⌋ ∑ t = 1 m i n ( a , b ) μ ( t ) ∑ x = 1 a [ t ∣ x ] ⌊ a x ⌋ [ g c d ( x , z ) = 1 ] ∑ y = 1 b [ t ∣ y ] ⌊ b y ⌋ [ g c d ( y , z ) = 1 ] = ∑ z = 1 c ⌊ c z ⌋ ∑ t = 1 m i n ( a , b ) μ ( t ) ∑ x = 1 ⌊ a t ⌋ ⌊ a t x ⌋ [ g c d ( t x , z ) = 1 ] ∑ y = 1 ⌊ b t ⌋ ⌊ b t y ⌋ [ g c d ( t y , z ) = 1 ] \sum_{i=1}^{a}\sum_{j=1}^{b}\sum_{k=1}^{c}d(ijk)\\ =\sum_{i=1}^{a}\sum_{j=1}^{b}\sum_{k=1}^{c}\sum_{x|i}\sum_{y|j}\sum_{z|k}[gcd(x,y)=gcd(x,z)=gcd(y,z)=1]\\ =\sum_{x=1}^{a}\sum_{y=1}^{b}\sum_{z=1}^{c}\left\lfloor\frac{a}{x}\right\rfloor\left\lfloor\frac{b}{y}\right\rfloor\left\lfloor\frac{c}{z}\right\rfloor[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]\\ =\sum_{x=1}^{a}\sum_{y=1}^{b}\sum_{z=1}^{c}\left\lfloor\frac{a}{x}\right\rfloor\left\lfloor\frac{b}{y}\right\rfloor\left\lfloor\frac{c}{z}\right\rfloor\sum_{t|x\wedge t|y}\mu(t)[gcd(x,z)=1][gcd(y,z)=1]\\ =\sum_{z=1}^{c}\left\lfloor\frac{c}{z}\right\rfloor\sum_{t=1}^{min(a,b)}\mu(t)\sum_{x=1}^{a}[t|x]\left\lfloor\frac{a}{x}\right\rfloor[gcd(x,z)=1]\sum_{y=1}^{b}[t|y]\left\lfloor\frac{b}{y}\right\rfloor[gcd(y,z)=1]\\ =\sum_{z=1}^{c}\left\lfloor\frac{c}{z}\right\rfloor\sum_{t=1}^{min(a,b)}\mu(t)\sum_{x=1}^{\left\lfloor\frac{a}{t}\right\rfloor}\left\lfloor\frac{a}{tx}\right\rfloor[gcd(tx,z)=1]\sum_{y=1}^{\left\lfloor\frac{b}{t}\right\rfloor}\left\lfloor\frac{b}{ty}\right\rfloor[gcd(ty,z)=1] i=1aj=1bk=1cd(ijk)=i=1aj=1bk=1cxiyjzk[gcd(x,y)=gcd(x,z)=gcd(y,z)=1]=x=1ay=1bz=1cxaybzc[gcd(x,y)=1][gcd(x,z)=1][gcd(y,z)=1]=x=1ay=1bz=1cxaybzctxtyμ(t)[gcd(x,z)=1][gcd(y,z)=1]=z=1czct=1min(a,b)μ(t)x=1a[tx]xa[gcd(x,z)=1]y=1b[ty]yb[gcd(y,z)=1]=z=1czct=1min(a,b)μ(t)x=1tatxa[gcd(tx,z)=1]y=1tbtyb[gcd(ty,z)=1]

发现我们只需要预处理出 g c d gcd gcd μ \mu μ函数即可做到 O ( n 2 log ⁡ n ) O(n^2\log n) O(n2logn)解决这个问题.

代码如下:

#include<bits/stdc++.h>
  using namespace std;

#define Abigail inline void
typedef long long LL;

const int N=2000;
const LL mod=1LL<<30;

int pr[N+9],tp,b[N+9];
LL mu[N+9],ans;

void sieve(int n){
  for (int i=2;i<=n;++i) b[i]=1;
  mu[1]=1;int v;
  for (int i=2;i<=n;++i){
  	if (b[i]) pr[++tp]=i,mu[i]=-1;
  	for (int j=1;j<=tp&&i*pr[j]<=n;++j){
  	  b[v=i*pr[j]]=0;
  	  if (i%pr[j]==0){mu[v]=0;break;}
  	  mu[v]=-mu[i];
  	}
  }
}

int A,B,C,gcd[N+9][N+9];

int GCD(int a,int b){return b?GCD(b,a%b):a;}

void pre_gcd(int n,int m){
  for (int i=1;i<=n;++i)
    for (int j=1;j<=m;++j)
      gcd[i][j]=GCD(i,j);
}

Abigail into(){
  scanf("%d%d%d",&A,&B,&C);
}

Abigail work(){
  sieve(min(A,B));
  pre_gcd(C,max(A,B));
  LL t1,t2,t3;
  for (int z=1;z<=C;++z){
  	t1=0;
  	for (int t=1;t<=min(A,B);++t){
  	  t2=t3=0;
  	  for (int x=t;x<=A;x+=t)
  	    t2=(t2+(LL)A/x*(gcd[z][x]==1))%mod;
  	  for (int y=t;y<=B;y+=t)
  	    t3=(t3+(LL)B/y*(gcd[z][y]==1))%mod;
  	  t1=(t1+mu[t]*t2*t3)%mod+mod;
  	  if (t1>=mod) t1-=mod;
  	}
  	ans=(ans+C/z*t1)%mod;
  }
}

Abigail outo(){
  printf("%I64d\n",ans);
}

int main(){
  into();
  work();
  outo();
  return 0;
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值