洛谷 P2257 YY的GCD 莫比乌斯反演

P2257 YY的GCD

学习数论之莫比乌斯反演、杜教筛推荐:peng-ym

推理:

令:                                                 

                                           f(x)=\sum_{i=1}^{n}\sum_{j=1}^{m}[gcd(i,j)=x]

我们要求的是: 

                                                   ans=\sum_{x\in prim}f(x)

 令

                                                    F(x)=\sum_{x|d}f(d)

   显然F(x)很容易求:                          

                                                    F(x)=\left \lfloor \frac{n}{x} \right \rfloor\left \lfloor \frac{m}{x} \right \rfloor

我们反演一下:

                                                  f(x)=\sum_{x|d}\mu (\frac{d}{x})F(d)

                                    ans=\sum_{x\in prim}f(x)=\sum_{x\in prim}\sum_{x|d}\mu (\frac{d}{x})F(d)

假设n<=m,我们变一下形:

                                            ans=\sum_{x\in prim}\sum_{d=1}^{\left \lfloor \frac{n}{x} \right \rfloor}\mu (d)F(dx)

枚举所有质数的所有倍数是不是可以换成枚举所有数的所有质因数,ok,我再变形:

                             ans=\sum_{T=2}^{n}\sum_{x\in prim,x|T}\mu (\frac{T}{x})F(T)=\sum_{T=2}^{n}F(T)\sum_{x\in prim,x|T}\mu (\frac{T}{x})

由于F(T)怎么求前面已经得知,所有我只用打表\sum_{x|T}\mu (\frac{T}{x}),然后用整除分块即可,这题就完美解决了。

注意一个超时的坑点:定义long long 类型的n,m会超时。

#include
#define ll long long
using namespace std;
const int maxn=1e7+10;
int prim[maxn],vis[maxn],mu[maxn],cnt;
ll g[maxn];
void get_mu(int n)
{
	mu[1]=1;
	for(int i=2;i<=n;i++)
	{
		if(!vis[i])
		mu[i]=-1,prim[++cnt]=i;
		for(int j=1;j<=cnt&&prim[j]*i<=n;j++)
		{
			vis[i*prim[j]]=1;
			if(i%prim[j]==0)break;
			else mu[prim[j]*i]=-mu[i];
		}
	}		
	for(int j=1;j<=cnt;j++)
	for(int i=1;i*prim[j]<=n;i++)
	g[i*prim[j]]+=mu[i];
	for(int i=1;i<=n;i++)
	g[i]=g[i-1]+g[i];
}
int main()
{
	
	int T,l,r,n,m;
	get_mu(1e7);
	scanf("%d",&T);
	while(T--)
	{
		ll ans=0;
		scanf("%d%d",&n,&m);
		if(n>m)swap(n,m);
		for(int l=2;l<=n;l=r+1)
		{
			r=min(n/(n/l),m/(m/l));
			ans+=1ll*n/l*(m/l)*(g[r]-g[l-1]);
		}
		printf("%lld\n",ans);
	}
}

 

 

 

你可能感兴趣的:(数学----莫比乌斯反演)