文章目录

题目链接:

https://www.spoj.com/problems/PGCD/
原来spoj知道题号不行啊。。要知道题的名字才行。。。然后改掉网址后面的题号就阔以了。。。
题意:就是求gcd(x,y)=质数 的个数
做过莫比乌斯的模板的就很清楚,不就是求f(2)+f(3)+f(5)+…+f§么?如果真是这样,那就是一道模板题,就没有什么意思了,果然,暴力这样求T掉了,嗯~不错不错

我们把相同 的F(n)的mu写在一起,就是F(n)*(mu(x1)+mu(x2)+…) 这样,阔以发现,x1,x2…都是n的质因子,然后就用一个Cnt[i]来记录 i 的所以质因子的莫比乌斯函数和,又因为要用到一段一段的,所以就用的是前缀和的那个套路就行了~

打个F的表,前面的系数mu 就不写了

#include"iostream"
#include"cstring"
#include"vector"
typedef long long LL;
using namespace std;
const int maxn=1e7+5;
char mu[maxn];
int Smu[maxn];
vector<int>prime;
bool vis[maxn];
int Cnt[maxn];//Cnt[i]表示i所有因子的mu的和 
int sum[maxn];
void Init(int n)
{
	memset(vis,1,sizeof(vis));
	mu[1]=1;
	Smu[1]=1;
	for(int i=2; i<=n; i++)
	{
		if(vis[i])
		{
			prime.push_back(i);
			mu[i]=-1;
		}
		for(int j=0; j<prime.size()&&i*prime[j]<=n; j++)
		{
			vis[i*prime[j]]=0;
			if(i%prime[j]==0)
			{
				mu[i*prime[j]]=0;
				break;
			}
			else mu[i*prime[j]]=-mu[i];
		}
		Smu[i]=Smu[i-1]+mu[i];
	}
	for(int i=1;i<=n;i++)
	{
		if(mu[i]==0)continue;
		for(int j=0;j<prime.size();j++)
		{
			if((LL)i*prime[j]>n)break;
			Cnt[i*prime[j]]+=mu[i]; 
		}
	}
	for(int i=1;i<=n;i++)sum[i]=sum[i-1]+Cnt[i];
}
long long F(int d,int n,int m)
{
	return (long long)(n/d)*(m/d);
}
int main()
{
	Init(maxn-5);
	int N,M,T;
	cin>>T;
	while(T--)
	{
		cin>>N>>M;
		LL ans=0;
		int n=min(N,M);
		for(int i=1,j;i<=n;i=j+1)
		{
			j=min(N/(N/i),M/(M/i));
			ans+=1LL*(sum[j]-sum[i-1])*F(i,N,M);
		}
		cout<<ans<<endl;
	}
}