LOJ#2476. 「2018 集训队互测 Day 3」蒜头的奖杯

题面

题解

(mathbf f' = mathbf f * mu)(G_{mathbf f} (n) = sum_{n | d} mathbf f(d)),记 ((i, j) = gcd(i, j))([i, j] = operatorname{lcm}(i, j))

(S_i=A_{id}, T_i = B_{id}, W_i = D_{id}, m = leftlfloor frac nd ight floor)

于是:

[egin{aligned} &sum_{i=1}^nsum_{j=1}^nsum_{k=1}^n A_iB_jC_kD_{(i, j)}E_{(i, k)}F_{(j, k)}\ =&sum_{k=1}^n C_ksum_{i=1}^nsum_{j=1}^n A_iB_jD_{(i, j)}sum_{p|i,p|k} E'_p sum_{q|j,q|k} F'_q\ =&sum_{[p, q] leq n} E'_{p} F'_qG_c([p, q]) sum_{pi leq n} A_{pi}sum_{qj leq n} B_{qj} D_{(pi,qj)}\ =&sum_{d=1}^nsum_{xyleq lfloor frac nd floor, (x,y) = 1} E'_{dx}F'_{dy}G_c(dxy)sum_{ixleq lfloor frac nd floor} A_{ixd} sum_{jy leq lfloor frac nd floor} B_{jyd} D_{d(ix,jy)}\ =&sum_{d=1}^nsum_{xyleq lfloor frac nd floor, (x,y) = 1} E'_{dx}F'_{dy}G_c(dxy)sum_{ix leq m} S_{ix} sum_{jy leq m} T_{yj} sum_{r|ix, r|jy} W'_r\ =&sum_{d=1}^nsum_{xyleq lfloor frac nd floor, (x,y) = 1} E'_{dx}F'_{dy}G_c(dxy)sum_{ix leq m} S_{ix} sum_{r|ix} W'_r sum_{r|jy} T_{jy}\ =&sum_{d=1}^nsum_{xyleq lfloor frac nd floor, (x,y) = 1} E'_{dx}F'_{dy}G_c(dxy)sum_{x | u} S_u sum_{r | u} W'_r sum_{r | v} [y | v] T_v end{aligned} ]

(x leq y)(x > y) 同理),先暴力枚举 (d),处理出 (S, T)(W),然后枚举 (x),那么后面三个 (sum) 相当于三次卷积,然后枚举和 (x) 互质的 (y) 即可,卷积可以用魔力筛优化到 (mathcal O(n log log n))

由于 (x leq sqrt n),所以时间复杂度为 (mathcal O(sum_{d=1}^n leftlfloor frac nd ight floor^{frac 32} log log leftlfloor frac nd ight floor) = mathcal O(n sqrt n log log n))

但是旧试题我卡不过去 /kk

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#define file(x) freopen(#x".in", "r", stdin), freopen(#x".out", "w", stdout)

const int N(1e5 + 10);
using ull = unsigned long long;
int n, prime[N], not_prime[N], cnt;
ull a[N], b[N], c[N], d[N], e[N], f[N], s[N], t[N], w[N], p[N], ans;

void F(ull *f, int N) { for (int j = 1; j <= cnt && prime[j] <= N; j++) for (int i = N / prime[j]; i; i--) f[i * prime[j]] -= f[i]; }
void G(ull *f, int N) { for (int j = 1; j <= cnt && prime[j] <= N; j++) for (int i = N / prime[j]; i; i--) f[i] += f[i * prime[j]]; }
void H(ull *f, int N) { for (int j = 1; j <= cnt && prime[j] <= N; j++) for (int i = 1; i * prime[j] <= N; i++) f[i * prime[j]] += f[i]; }

int main()
{
	scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%llu", a + i);
	for (int i = 1; i <= n; i++) scanf("%llu", b + i);
	for (int i = 1; i <= n; i++) scanf("%llu", c + i);
	for (int i = 1; i <= n; i++) scanf("%llu", d + i);
	for (int i = 1; i <= n; i++) scanf("%llu", e + i);
	for (int i = 1; i <= n; i++) scanf("%llu", f + i);
	for (int i = 2; i <= n; i++)
	{
		if (!not_prime[i]) prime[++cnt] = i;
		for (int j = 1; j <= cnt && i * prime[j] <= n; j++)
			{ not_prime[i * prime[j]] = 1; if (!(i % prime[j])) continue; }
	}
	F(e, n), F(f, n), G(c, n);
	for (int i = 1, m; i <= n; i++)
	{
		m = n / i;
		for (int j = 1; j <= m; j++) p[j] = a[j * i], t[j] = b[j * i], w[j] = d[j * i]; F(w, m);
		for (int x = 1; x * x <= m; x++)
		{
			std::memset(s, 0, (m + 1) << 3);
			for (int j = x; j <= m; j += x) s[j] = p[j]; G(s, m);
			for (int j = 1; j <= m; j++) s[j] *= w[j]; H(s, m);
			for (int j = 1; j <= m; j++) s[j] *= t[j]; G(s, m);
			for (int y = x; x * y <= m; y++) if (std::__gcd(x, y) == 1)
				ans += e[x * i] * f[y * i] * c[x * y * i] * s[y];
			std::memset(s, 0, (m + 1) << 3);
			for (int j = x; j <= m; j += x) s[j] = t[j]; G(s, m);
			for (int j = 1; j <= m; j++) s[j] *= w[j]; H(s, m);
			for (int j = 1; j <= m; j++) s[j] *= p[j]; G(s, m);
			for (int y = x + 1; x * y <= m; y++) if (std::__gcd(x, y) == 1)
				ans += e[y * i] * f[x * i] * c[x * y * i] * s[y];
		}
	}
	printf("%llu
", ans);
	return 0;
}
原文地址:https://www.cnblogs.com/cj-xxz/p/13519647.html