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 }

 

posted @ 2016-03-30 20:30  HugeGun  阅读(152)  评论(0编辑  收藏  举报