Loading

题解 [SDOI2018]旧试题

蒟蒻语

50 道黑题,写篇题解祭一下 /cy

蒟蒻解

\( \begin{aligned} &\sum\limits_{i=1}^{A} \sum\limits_{j=1}^{B} \sum\limits_{k=1}^{C} d(i, j, k)\\ &= \sum\limits_{i=1}^{A} \sum\limits_{j=1}^{B} \sum\limits_{k=1}^{C} \sum\limits_{x|i} \sum\limits_{y|j} \sum\limits_{z|k} [\gcd(x, y) = 1][\gcd(y, z) = 1][\gcd(z, x) = 1]\\ &= \sum\limits_{x=1}^{A} \sum\limits_{y=1}^{B} \sum\limits_{z=1}^{C} [\gcd(x, y) = 1][\gcd(y, z) = 1][\gcd(z, x) = 1] \left\lfloor\frac{A}{x}\right\rfloor \left\lfloor\frac{B}{y}\right\rfloor \left\lfloor\frac{C}{z}\right\rfloor\\ &= \sum\limits_{d_1=1}^{A} \mu(d_1)\sum\limits_{d_2=1}^{B} \mu(d_2) \sum\limits_{d_3=1}^{C} \mu(d_3) \sum\limits_{x=1}^{ \left\lfloor\frac{A}{\operatorname{lcm}(d_1,d_2)}\right\rfloor} \left\lfloor\frac{A}{\operatorname{lcm}(d_1,d_2)x}\right\rfloor \sum\limits_{y=1}^{ \left\lfloor\frac{B}{\operatorname{lcm}(d_2,d_3)}\right\rfloor} \left\lfloor\frac{B}{\operatorname{lcm}(d_2,d_3)y}\right\rfloor \sum\limits_{z=1}^{ \left\lfloor\frac{C}{\operatorname{lcm}(d_3,d_1)}\right\rfloor} \left\lfloor\frac{C}{\operatorname{lcm}(d_3,d_1)z}\right\rfloor\\ \end{aligned} \)

(设 \(Max = \max (A, B, C)\))

考虑哪些三元组会有贡献。

  1. \(\mu(d_1), \mu(d_2), \mu(d_3)\) 不为 \(0\)
  2. \(\operatorname{lcm}(d_1,d_2) , \operatorname{lcm}(d_2,d_3), \operatorname{lcm}(d_3,d_1) \le Max\)

把一个数看成一个点。

首先我们把 \(\mu(x)\)\(0\) 的点排除在外。

然后把 \(\operatorname{lcm}(x, y) \le Max\) 的点连接起来。

然后再做一遍三元环计数就好了,暴力枚举每一个三元环统计答案。为了更快地统计答案,可以先把边定向。

这样的时间复杂度是 \(O(m \sqrt m)\) 的。( \(m\) 是边数)

事实上,边数最多只有 \(821535\) 条 (用蒟蒻劣质的程序算出来)

因此这道题就被解决了

蒟蒻码

#include<bits/stdc++.h>
#define L(i, j, k) for(int i = j; i <= k; i++)
#define R(i, j, k) for(int i = j; i >= k; i--)
#define ll long long
using namespace std;
const int N = 1e5 + 7;
const int M = 1e6 + 7;
const int mod = 1e9 + 7;
bool Prime[N];
int tot, P[N >> 3], mu[N];
void xxs() {
	mu[1] = 1;
	L(i, 2, 1e5)  {
		if(!Prime[i]) P[++tot] = i, mu[i] = -1;
		for(int j = 1; P[j] * i <= 1e5 && j <= tot; j++) {
			Prime[P[j] * i] = 1;
			if(i % P[j] == 0) {
				mu[P[j] * i] = 0;
				break;
			}
			mu[P[j] * i] = -mu[i];
		}
	}
} 
vector<int> ve[N];
unordered_map<int, bool> mp[N];
int T, Max, A, B, C, ans, p[N];
int sA[M], sB[M], sC[M], cnt, deg[N];
int gcd(int x, int y) { return x == 0 ? y : gcd(y % x, x); }
ll lcm(int x, int y) { return 1ll * x / gcd(x, y) * y; }
int ta, tb, tc, sum;
void dh(int a, int b, int c) {
	(sum += 1ll * p[a / ta] * p[b / tb] % mod * p[c / tc] % mod) %= mod;
}
void get(int a, int b, int c) {
	sum = 0;
	if(a == b && b == c) dh(A, B, C);
	else if(a == b || b == c || c == a) dh(A, B, C), dh(C, A, B), dh(B, C, A);
	else dh(A, B, C), dh(A, C, B), dh(B, A, C), dh(B, C, A), dh(C, A, B), dh(C, B, A);
	(ans += (mu[a] * mu[b] * mu[c] * sum % mod + mod) % mod) %= mod;
}
int vis[N];
void js() {
	L(i, 1, cnt) {
		int &u = sA[i], &v = sB[i];
		if(deg[u] > deg[v]) swap(u, v);
		else if(deg[u] == deg[v] && u > v) swap(u, v);
		ve[u].push_back(i);
	}
	L(i, 1, Max) {
		for(int j : ve[i]) vis[sB[j]] = sC[j];
		for(int j : ve[i]) for(int k : ve[sB[j]]) 
			if(vis[sB[k]]) ta = vis[sB[k]], tb = sC[j], tc = sC[k], get(i, sB[j], sB[k]);
		for(int j : ve[i]) vis[sB[j]] = 0;
	}
}
void getans(int x) {
	for(int l = 1, r; l <= x; l = r + 1) {
		r = (x / (x / l));
		(p[x] += 1ll * (r - l + 1) * (x / l) % mod) %= mod;
	}
}
int main() {
	scanf("%d", &T);
	xxs();
	L(i, 1, 1e5) getans(i);
	while(T--) {
		scanf("%d%d%d", &A, &B, &C);
		ans = cnt = 0;
		Max = max(max(A, B), C);
		R(i, Max, 1) for(int j = i; j <= Max; j += i) {
				if(!mu[j]) continue;
				for(int k = j; k <= 1ll * Max * i / j; k += i) {
					if(!mu[k]) continue;
					if(!mp[j][k]) ++cnt, sA[cnt] = j, sB[cnt] = k, sC[cnt] = j / i * k, deg[j] ++, deg[k] ++, mp[j][k] = 1;
				}
			}
		js();
		L(i, 1, Max) ve[i].clear(), mp[i].clear(), deg[i] = 0;
		printf("%d\n", (ans + mod) % mod);
	}
	return 0;
}
posted @ 2020-10-04 22:31  zhoukangyang  阅读(53)  评论(0编辑  收藏  举报