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 = \left\lfloor \frac nd \right\rfloor\)

于是:

\[\begin{aligned} &\sum_{i=1}^n\sum_{j=1}^n\sum_{k=1}^n A_iB_jC_kD_{(i, j)}E_{(i, k)}F_{(j, k)}\\ =&\sum_{k=1}^n C_k\sum_{i=1}^n\sum_{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}^n\sum_{xy\leq \lfloor \frac nd \rfloor, (x,y) = 1} E'_{dx}F'_{dy}G_c(dxy)\sum_{ix\leq \lfloor \frac nd \rfloor} A_{ixd} \sum_{jy \leq \lfloor \frac nd \rfloor} B_{jyd} D_{d(ix,jy)}\\ =&\sum_{d=1}^n\sum_{xy\leq \lfloor \frac nd \rfloor, (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}^n\sum_{xy\leq \lfloor \frac nd \rfloor, (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}^n\sum_{xy\leq \lfloor \frac nd \rfloor, (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 \left\lfloor \frac nd \right\rfloor^{\frac 32} \log \log \left\lfloor \frac nd \right\rfloor) = \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\n", ans);
	return 0;
}
posted @ 2020-08-17 19:56  xgzc  阅读(296)  评论(0编辑  收藏  举报