莫比乌斯反演套路一--令t=pd--BZOJ2820: YY的GCD

t<=10000组询问:有多少x,y,满足$x\epsilon [1,n],y\epsilon [1,m],(x,y)为质数$。n,m<=1e7。

首先式子列出来,f(i)--1<=x<=n,1<=y<=m中有多少(x,y)=i,g(i)--1<=x<=n,1<=y<=m中有多少i|(x,y),$g(i)=\sum_{i|d} f(d) ------> f(i)=\sum_{i|d} \mu(\frac{d}{i})g(d)$,而$g(i)=\frac{n}{i}\frac{m}{i}$,因此$f(i)=\sum_{i|d} \mu(\frac{d}{i})\frac{n}{d}\frac{m}{d}$,而(x,y)=k的充要条件是(x/k,y/k)=1,因此答案就$ans=\sum_{p是质数}^{min(n,m)}\sum_{d=1}^{min(n,m)}\mu(d)\frac{n}{pd}\frac{m}{pd}=\sum_{t=1}^{min(n,m)}\frac{n}{t}\frac{m}{t}\sum_{p|t}\mu(\frac{t}{p})$

前面那个sigma可以根号解决,而后面那个东西只跟t有关,因此预处理下即可。

 1 //#include<iostream>
 2 #include<cstring>
 3 #include<cstdlib>
 4 #include<cstdio>
 5 //#include<bitset>
 6 #include<algorithm>
 7 //#include<cmath>
 8 using namespace std;
 9 
10 int T,n,m;
11 #define maxn 10000011
12 int miu[maxn],prime[maxn],lp,summiu[maxn]; bool notprime[maxn];
13 void pre(int n)
14 {
15     lp=0; miu[1]=1; summiu[1]=0;
16     for (int i=2;i<=n;i++)
17     {
18         if (!notprime[i]) {prime[++lp]=i; miu[i]=-1;}
19         for (int j=1;j<=lp && 1ll*prime[j]*i<=n;j++)
20         {
21             notprime[i*prime[j]]=1;
22             if (i%prime[j]) miu[i*prime[j]]=-miu[i];
23             else {miu[i*prime[j]]=0; break;}
24         }
25     }
26     for (int i=1;i<=lp;i++)
27         for (int j=prime[i],cnt=1;j<=n;j+=prime[i],cnt++)
28             summiu[j]+=miu[cnt];
29     for (int i=1;i<=n;i++) summiu[i]+=summiu[i-1];
30 }
31 
32 #define LL long long
33 int main()
34 {
35     pre(10000001);
36     scanf("%d",&T);
37 while (T--)
38 {
39     scanf("%d%d",&n,&m);
40     LL ans=0;
41     for (int i=1,to=min(n,m),last;i<=to;i=last+1)
42     {
43         last=min(n/(n/i),m/(m/i));
44         ans+=1ll*(n/i)*(m/i)*(summiu[last]-summiu[i-1]);
45     }
46     printf("%lld\n",ans);
47 }
48     return 0;
49 }
View Code

 

posted @ 2018-01-01 20:44  Blue233333  阅读(325)  评论(0编辑  收藏  举报