「题解」Luogu P6055 [RC-02] GCD

P6055 [RC-02] GCD

Description

  • 给定 \(n\),求

    \[\sum_{i = 1}^n \sum_{j = 1}^n \sum_{p = 1}^{\left\lfloor\frac{n}{j}\right\rfloor} \sum_{q = 1}^{\left\lfloor\frac{n}{j}\right\rfloor} [\gcd(i, j) = 1] [\gcd(p, q) = 1] \bmod 998244353 \]

  • \(n\le 2\times 10^9\)

Solution

神仙思维题。

\(p, q\) 的上界均为 \(\left\lfloor\dfrac{n}{j}\right\rfloor\),相当于都除以 \(j\),又因为要求 \(\gcd(p, q) = 1\),所以 \(j\) 就相当于 \(\gcd(pj, qj)\)

于是把 \(j\) 扔掉,令 \(p' = pj, q' = qj\)

\[\begin{aligned} \sum_{i = 1}^n \sum_{p' = 1}^n \sum_{q' = 1}^n [\gcd(i, \gcd(p', q')) = 1] & = \sum_{i = 1}^n \sum_{p' = 1}^n \sum_{q' = 1}^n [\gcd(i, p', q') = 1] \\ & = \sum_{d = 1}^n \mu(d) \left\lfloor\dfrac{n}{d}\right\rfloor^3 \end{aligned} \]

杜教筛 \(\mu\) 即可。

Code

// 18 = 9 + 9 = 18.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <unordered_map>
#define Debug(x) cout << #x << "=" << x << endl
typedef long long ll;
using namespace std;

namespace IO
{
	int len = 0;
	char buf[(1 << 20) + 1], *S, *T;
	#if ONLINE_JUDGE
		#define Getchar() (S == T ? T = (S = buf) + fread(buf, 1, (1 << 20) + 1, stdin), (S == T ? EOF : *S++) : *S++)
	#else
		#define Getchar() getchar()
	#endif
	#define re register
	inline int read()
	{
		re char c = Getchar();
		re int x = 0;
		while (c < '0' || c > '9')
			c = Getchar();
		while (c >= '0' && c <= '9')
			x = (x << 3) + (x << 1) + (c ^ 48), c = Getchar();
		return x;
    }
}
using IO::read;

const int MOD = 998244353;
int add(int a, int b) {return (a + b) % MOD;}
int sub(int a, int b) {return (a - b + MOD) % MOD;}
int mul(int a, int b) {return (ll)a * b % MOD;}

const int MAXN = 1587401 + 5;
const int N = 1587401;

int p[MAXN], mu[MAXN], muS[MAXN];
bool vis[MAXN];

void pre()
{
	mu[1] = 1;
	for (int i = 2; i <= N; i++)
	{
		if (!vis[i])
		{
			p[++p[0]] = i;
			mu[i] = -1;
		}
		for (int j = 1; j <= p[0] && i * p[j] <= N; j++)
		{
			vis[i * p[j]] = true;
			if (i % p[j] == 0)
			{
				mu[i * p[j]] = 0;
				break;
			}
			mu[i * p[j]] = mu[i] * mu[p[j]];
		}
	}
	for (int i = 1; i <= N; i++)
	{
		muS[i] = muS[i - 1] + mu[i];
	}
}

unordered_map<int, int> dp;

int sublinear(int n)
{
	if (n <= N)
	{
		return muS[n];
	}
	if (dp.find(n) != dp.end())
	{
		return dp[n];
	}
	int res = 1;
	for (int l = 2, r; l <= n; l = r + 1)
	{
		int k = n / l;
		r = n / k;
		res = sub(res, mul(r - l + 1, sublinear(k)));
	}
	return dp[n] = res;
}

int GetSum(int l, int r)
{
	return sublinear(r) - sublinear(l - 1);
}

int block(int n)
{
	int res = 0;
	for (int l = 1, r; l <= n; l = r + 1)
	{
		int k = n / l;
		r = n / k;
		res = add(res, mul(GetSum(l, r), mul(k, mul(k, k))));
	}
	return res;
}

int main()
{
	pre();
	int n = read();
	printf("%d\n", add(block(n), MOD));
	return 0;
}
posted @ 2022-03-10 13:37  mango09  阅读(19)  评论(0编辑  收藏  举报
-->