bzoj2301 [HAOI2011]Problem b
莫比乌斯反演。。。
首先可以把原问题拆成四个子问题,这个就不赘述了。。。
现在转化成求有多少个数对满足$1\leqslant a\leqslant n,1\leqslant b\leqslant m$且$gcd(a,b)=1$
我们来推一推式子:
因为:$\sum\limits_{d|n}=\mu(d)=[n=1]$
所以:$\sum\limits_{a=1}^n\sum\limits_{b=1}^m [gcd(a,b)=1]$
$\Rightarrow$
$\sum\limits_{a=1}^n\sum\limits_{b=1}^m\ \sum\limits_{d|gcd(a,b)}\mu(d)$
$\Rightarrow$
$\sum\limits_{d=1}^{min(n,m)}\mu(d)\sum\limits_{d|a,a=1}^n\ \sum\limits_{d|b,b=1}^m 1$
$\Rightarrow$
$\sum\limits_{d=1}^{min(n,m)}\mu(d){\left\lfloor{\frac{n}{d}}\right\rfloor}{\left\lfloor{\frac{m}{d}} \right\rfloor}$
分段优化一下枚举就好了
1 #include<iostream> 2 #include<cstdio> 3 #include<cstdlib> 4 #include<string> 5 #include<cstring> 6 #include<cmath> 7 #define re(i,l,r) for(int i=(l);i<=(r);i++) 8 #define rre(i,r,l) for(int i=(r);i>=(l);i--) 9 using namespace std; 10 typedef long long LL; 11 int prime[50050],bo[50050],mu[50050],prime_tot,sum[50050]; 12 LL solve(int n,int m) 13 { 14 if(n<=0||m<=0)return 0; 15 if(n>m)swap(n,m); 16 LL ret=0; 17 int l=1,xia=0; 18 while(l<=n) 19 { 20 xia=min(n/(n/l),m/(m/l)); 21 ret+=1LL*(sum[xia]-sum[l-1])*(n/l)*(m/l); 22 l=xia+1; 23 } 24 return ret; 25 } 26 int t,a,b,c,d,k; 27 int main() 28 { 29 mu[1]=1; 30 re(i,2,50000) 31 { 32 if(!bo[i])prime[++prime_tot]=i,mu[i]=-1; 33 for(int j=1;j<=prime_tot&&i*prime[j]<=50000;j++) 34 { 35 bo[i*prime[j]]=1; 36 if(i%prime[j]==0){mu[i*prime[j]]=0;break;} 37 else mu[i*prime[j]]=-mu[i]; 38 } 39 } 40 re(i,1,50000)sum[i]=sum[i-1]+mu[i]; 41 scanf("%d",&t); 42 while(t--) 43 { 44 scanf("%d%d%d%d%d",&a,&b,&c,&d,&k); 45 printf("%lld\n", 46 solve(b/k,d/k)- 47 solve((a-1)/k,d/k)- 48 solve(b/k,(c-1)/k)+ 49 solve((a-1)/k,(c-1)/k)); 50 } 51 return 0; 52 }