P2257 YY的GCD (莫比乌斯反演)

题意:求$$\sum_{i=1}{n}\sum_{j=1}[gcd(i,j) = prim]$$
题解:那就开始化式子吧!!

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

\[F(x) = \sum_{d|x} f(d) = \left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{x} \right \rfloor \]

\[f(d) = \sum_{d|x} \mu\left ( \frac{x}{d} \right )F(x) \]

\[ans= \sum_{p \in prim}f(p)=\sum_{p \in prim}\sum_{p|x} \mu\left ( \frac{x}{p} \right )\left \lfloor \frac{n}{x} \right \rfloor \left \lfloor \frac{m}{x} \right \rfloor \]

\[ans = \sum_{p\in prim}\sum_{t = 1}^{min(\left \lfloor \frac{n}{p} \right \rfloor,\left \lfloor \frac{m}{p} \right \rfloor)}\mu(t)\left \lfloor \frac{n}{pt} \right \rfloor\left \lfloor \frac{m}{pt} \right \rfloor \]

  令pt = T

\[ans=\sum_{T=1}^{min(n, m)}\left \lfloor \frac{n}{T} \right \rfloor\left \lfloor \frac{m}{T} \right \rfloor\sum_{p | T, p\in prim}\mu(\frac{T}{p}) \]

  后面部分显然可以预处理

// luogu-judger-enable-o2
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;

bool vis[10000005];
int prim[10000005];
int mu[10000005];
int g[10000005];
ll sum[10000005];
int cnt;

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 && i * prim[j] <= n; j++)
		{
			vis[i * prim[j]] = 1;
			if(i % prim[j] == 0) break;
			else mu[i * prim[j]] -= mu[i];
		}
	}
	
	for(int i = 1; i <= cnt; i++)
		for(int j = 1; j * prim[i] <= n; j++) g[j * prim[i]] += mu[j];
	for(int i = 1; i <= n; i++) sum[i] = sum[i - 1] + (ll)g[i];
}

int main()
{
	cnt = 0;
	get_mu(10000000);
	int T;
	scanf("%d", &T);
	while(T--)
	{
		int n, m;
		scanf("%d%d", &n, &m);
		if(n > m) swap(n, m);
		ll ans = 0;
		for(int i = 1, r; i <= n; i = r + 1)
		{
			r = min(n / (n / i), m / (m / i));
			ans += 1LL * (n / i) * (m / i) * (sum[r] - sum[i - 1]);
		}
		printf("%lld\n", ans);
	}
	return 0;
}
posted @ 2019-02-01 17:49  lwqq3  阅读(189)  评论(1编辑  收藏  举报