BZOJ 3994 [SDOI2015]约数个数和 (莫比乌斯反演)
题目大意:略
首先要知道这样一个公式不知道这个公式这道题还怎么做...
$d(ij)=\sum\limits_{x=1}^{i} \sum\limits_{y=1}^{j}[gcd(x,y)==1]$
具体证明可以参考这位神犇的博客
大意是说,令$k=i \cdot j$,把$k,i,j$都分解成质因子幂次乘积的形式
那么对于其中一个质因子$p$,$k,i,j$里,$p$的幂次分别为$c,a,b$
那么因为$p^{c}=p^{a} \cdot p^{b},c=a+b$
对于$k$的所有约数,$p$能取的幂次是$0,1,2...c$,一共$c+1=a+b+1$种取值
而在上述式子中,保证$x,y$互质,则$x,y$中$p$的指数,$x$取$0$,$y$取$[1,b]$,或者$x$取$[1,a]$,$y$取$0$,或者$x,y$都取$0$,一共$a+b+1$种取值,和上述论证吻合
而质因子之间互不影响,所以推广到多个质因子上,这个结论依然是正确的
进入正题,我们有了这个公式,下面的推导就十分经典套路了
$\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m} \sum\limits_{x|i} \sum\limits_{y|j} [gcd(x,y)==1]$
$\sum\limits_{i=1}^{n} \sum\limits_{j=1}^{m} \sum\limits_{x|i} \sum\limits_{y|j} \sum\limits_{d|gcd(x,y)} \mu(d)$
$\sum\limits_{d=1}^{n} \mu(d) \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}\sum\limits_{x|i}\sum\limits_{y|j}[d|gcd(x,y)]$
$\sum\limits_{d=1}^{n} \mu(d) \sum\limits_{x=1}^{n}\sum\limits_{y=1}^{m} \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{y} \right \rfloor [d|gcd(x,y)]$
$\sum\limits_{d=1}^{n} \mu(d) \sum\limits_{x=1}^{n} \left \lfloor \frac{n}{dx} \right \rfloor \sum\limits_{y=1}^{m} \left \lfloor \frac{m}{dy} \right \rfloor$
令$g(n)=\sum\limits_{x=1}^{n} \left \lfloor \frac{n}{x} \right \rfloor$
则$\sum\limits_{d=1}^{n} \mu(d) g(\left \lfloor \frac{n}{d} \right \rfloor) g(\left \lfloor \frac{m}{d} \right \rfloor )$
$g(n)$可以利用整除分块的思想在$O(n\sqrt n)$的时间内预处理出来
对于每个询问也用整除分块求解即可,总时间$O(T\sqrt n+n\sqrt n)$
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define N1 50010 5 #define ll long long 6 #define dd double 7 #define inf 2147483647 8 #define maxn 50000 9 using namespace std; 10 11 ll g[N1]; 12 int pr[N1],mu[N1],smu[N1],use[N1],cnt; 13 void init() 14 { 15 int n,i,j,la; 16 for(n=1;n<=maxn;n++) 17 { 18 for(i=1;i<=n;i=la+1) 19 { 20 la=(n/(n/i)); 21 g[n]+=1ll*(la-i+1)*(n/i); 22 } 23 } 24 for(mu[1]=smu[1]=1,i=2;i<=maxn;i++) 25 { 26 if(!use[i]){ pr[++cnt]=i; mu[i]=-1; } 27 for(j=1;j<=cnt&&i*pr[j]<=maxn;j++) 28 { 29 use[i*pr[j]]=1; 30 if(i%pr[j]){ mu[i*pr[j]]=-mu[i]; } 31 else break; 32 } 33 smu[i]=smu[i-1]+mu[i]; 34 } 35 } 36 int n,m,T; 37 38 int main() 39 { 40 scanf("%d",&T); 41 init(); 42 int i,j,la;ll ans=0; ll inv,y; 43 while(T--) 44 { 45 scanf("%d%d",&n,&m); if(n>m) swap(n,m); ans=0; 46 for(i=1;i<=n;i=la+1) 47 { 48 la=min(n/(n/i),m/(m/i)); 49 ans+=1ll*(smu[la]-smu[i-1])*g[n/i]*g[m/i]; 50 } 51 printf("%lld\n",ans); 52 } 53 return 0; 54 }