BZOJ2820 YY的GCD题解(Mobius反演+除法分块)

题目:BZOJ2820.
题目大意:求有多少对 x , y x,y x,y满足 1 ≤ x ≤ n , 1 ≤ y ≤ m 1\leq x \leq n,1\leq y \leq m 1xn,1ym g c d ( x , y ) gcd(x,y) gcd(x,y)为质数.
1 ≤ n , m ≤ 1 0 7 1\leq n,m\leq 10^7 1n,m107,数据组数 = 1 0 4 =10^4 =104.

设素数集为P,那么题目要求即为:
∑ p ∈ P ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] \sum_{p\in P}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p] pPi=1nj=1m[gcd(i,j)=p]

钦定 n ≤ m n\leq m nm,设 a = ⌊ n p ⌋ , b = ⌊ m p ⌋ a=\left \lfloor \frac{n}{p} \right \rfloor,b=\left \lfloor \frac{m}{p} \right \rfloor a=pn,b=pm,那么:
∑ p ∈ P ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ p ∈ P ∑ i = 1 a ∑ j = 1 b [ g c d ( i , j ) = 1 ] = ∑ p ∈ P ∑ i = 1 a ∑ j = 1 b ∑ d ∣ i ∧ d ∣ j μ ( d ) = ∑ d = 1 ⌊ n p ⌋ ∑ p ∈ P μ ( d ) ⌊ n p d ⌋ ⌊ m p d ⌋ \sum_{p\in P}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p]\\ =\sum_{p\in P}\sum_{i=1}^{a}\sum_{j=1}^{b}[gcd(i,j)=1]\\ =\sum_{p\in P}\sum_{i=1}^{a}\sum_{j=1}^{b}\sum_{d|i\wedge d|j}\mu(d)\\ =\sum_{d=1}^{\left\lfloor\frac{n}{p}\right\rfloor}\sum_{p\in P} \mu(d)\left\lfloor\frac{n}{pd} \right\rfloor\left\lfloor\frac{m}{pd}\right\rfloor\\ pPi=1nj=1m[gcd(i,j)=p]=pPi=1aj=1b[gcd(i,j)=1]=pPi=1aj=1bdidjμ(d)=d=1pnpPμ(d)pdnpdm

k = p d k=pd k=pd,那么:
∑ p ∈ P ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ k = 1 n ∑ p ∈ P ∧ p ∣ k μ ( k p ) ⌊ n k ⌋ ⌊ m k ⌋ \sum_{p\in P}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p]\\ =\sum_{k=1}^{n}\sum_{p\in P\wedge p|k}\mu(\frac{k}{p})\left\lfloor\frac{n}{k} \right\rfloor\left\lfloor\frac{m}{k}\right\rfloor pPi=1nj=1m[gcd(i,j)=p]=k=1npPpkμ(pk)knkm

设一个函数: f ( k ) = ∑ p ∈ P ∧ p ∣ k μ ( k p ) f(k)=\sum_{p\in P\wedge p|k}\mu(\frac{k}{p}) f(k)=pPpkμ(pk),那么:
∑ p ∈ P ∑ i = 1 n ∑ j = 1 m [ g c d ( i , j ) = p ] = ∑ k = 1 n f ( k ) ⌊ n k ⌋ ⌊ m k ⌋ \sum_{p\in P}\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=p]=\sum_{k=1}^{n}f(k)\left\lfloor\frac{n}{k} \right\rfloor\left\lfloor\frac{m}{k}\right\rfloor pPi=1nj=1m[gcd(i,j)=p]=k=1nf(k)knkm

发现这个式子中,只要 f f f函数能够用线性筛筛出即可用除法分块做到 O ( n + m ) O(\sqrt{n}+\sqrt{m}) O(n +m )求解,所以尝试推导这个函数在线性筛三种情况下的值:
1.当 i i i为质数时,显然 f ( i ) = 1 f(i)=1 f(i)=1.
2.当 g c d ( i , p r [ j ] ) = 1 gcd(i,pr[j])=1 gcd(i,pr[j])=1时,可以推导:
KaTeX parse error: Expected '}', got '\wdge' at position 27: …\\=\sum_{p\in P\̲w̲d̲g̲e̲ ̲p|(i*pr[j])}\mu…

3.当 p r [ j ] ∣ i pr[j]|i pr[j]i时,可以推导:
f ( i ∗ p r [ j ] ) = ∑ p ∈ P ∧ p ∣ ( i ∗ p r [ j ] ) μ ( i ∗ p r [ j ] p ) = μ ( i ∗ p r [ j ] p r [ j ] ) + ∑ p ∈ P ∧ p ∣ i μ ( i ∗ p r [ j ] p ) = μ ( i ) f(i*pr[j])\\ =\sum_{p\in P\wedge p|(i*pr[j])}\mu(\frac{i*pr[j]}{p})\\ =\mu(\frac{i*pr[j]}{pr[j]})+\sum_{p\in P\wedge p|i}\mu(\frac{i*pr[j]}{p})\\ =\mu(i) f(ipr[j])=pPp(ipr[j])μ(pipr[j])=μ(pr[j]ipr[j])+pPpiμ(pipr[j])=μ(i)

发现我们就这么把 f f f函数筛出来了,所以除法分块一下就可以了,时间复杂度 O ( m + T m ) O(m+T\sqrt m) O(m+Tm ).

代码如下:

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

#define Abigail inline void
typedef long long LL;

const int N=10000000;

int n,m;
int pr[N+9],tp,b[N+9];
LL mu[N+9],f[N+9];

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

LL Query(int n,int m){
  if (n>m) swap(n,m);
  LL ans=0; 
  for (int l=1,r;l<=n;l=r+1){
    r=min(n/(n/l),m/(m/l));
    ans+=(f[r]-f[l-1])*(n/l)*(m/l);
  }
  return ans;
}

Abigail start(){
  sieve(N);
}

Abigail into(){
  scanf("%d%d",&n,&m);
}

Abigail outo(){
  printf("%lld\n",Query(n,m));
}

int main(){
  start();
  int T;
  scanf("%d",&T);
  while (T--){
  	into();
  	outo();
  }
  return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值