[洛谷P2257] YY的GCD

前言

板题2号

题目

洛谷

讲解

若求 \(\sum_{i=1}^n\sum_{j=1}^m[gcd(i,j)=p]\),其中 \(p\) 为定值

\(f(k)=\sum_{i=1}^{\frac{\min(n,m)}{p}}\mu(i)\lfloor\dfrac{n}{ip}\rfloor\lfloor\dfrac{m}{ip}\rfloor\)

\(p\) 为任意质数,即求 \(\sum_{p\in prime}\sum_{i=1}^{\frac{\min(n,m)}{p}}\mu(i)\lfloor\dfrac{n}{ip}\rfloor\lfloor\dfrac{m}{ip}\rfloor\)

换元后得到 \(\sum_{p\in prime}\sum_{p|t}\mu(\dfrac{t}{p})\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\)

我们来枚举\(t\),得到 \(\sum_{t=1}^{\min(n,m)}\sum_{p|t}\mu(\dfrac{t}{p})\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\)

把与 \(p\) 无关的两项提出来:

\(\sum_{t=1}^{\min(n,m)}\lfloor\dfrac{n}{t}\rfloor\lfloor\dfrac{m}{t}\rfloor\sum_{p|t}\mu(\dfrac{t}{p})\)

\(s(t)=\sum_{p|t}\mu(\dfrac{t}{p})\)

预处理 \(s\) 即可

代码

int mu[MAXN],prime[MAXN],pn,s[MAXN];
bool vis[MAXN];
void sieve(int x)
{
	mu[1] = 1;
	for(int i = 2;i <= x;++ i)
	{
		if(!vis[i]) prime[++pn] = i,mu[i] = -1;
		for(int j = 1;j <= pn && i * prime[j] <= x;++ j)
		{
			vis[i * prime[j]] = 1;
			if(i % prime[j] == 0) break;
			mu[i * prime[j]] = -mu[i];
		}
	}
	for(int i = 1;i <= pn;++ i)
		for(int j = prime[i];j <= x;j += prime[i])
			s[j] += mu[j / prime[i]];
	for(int i = 1;i <= x;++ i) s[i] += s[i-1];
}

LL solve(int x,int y)
{
	if(x > y) swap(x,y);
	LL ret = 0;
	for(int l = 1,r;l <= x;l = r+1)
	{
		r = Min(x/(x/l),y/(y/l));
		ret += 1ll * (s[r] - s[l-1]) * (x/l) * (y/l);
	}
	return ret;
}

int main()
{
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	sieve(10000019); 
	for(int T = Read(); T ;-- T)
	{
		n = Read(); m = Read();
		Put(solve(n,m),'\n');
	}
	return 0;
}
posted @ 2021-01-09 17:42  皮皮刘  阅读(39)  评论(0编辑  收藏  举报