name 题解

题面描述

给定一个长度为 nn 的数列 a1,a2,a3,,ana_1, a_2, a_3, \dots, a_n

k=(i=1nj=i+1nlcm(ai,aj))mod3999971\displaystyle k=(\sum_{i=1}^{n}\sum_{j=i+1}^{n}\mathrm{lcm}(a_i,a_j)) \bmod 3999971,求一个 k+1k+1 的正整数倍 SS,使得 SS 的数位累加和最小。

解题思路

首先我们先考虑如何求出 kk

注意到 i=1nj=i+1nlcm(ai,aj)\displaystyle \sum_{i=1}^{n}\sum_{j=i+1}^{n}\mathrm{lcm}(a_i,a_j) 第二个 \sum 不是从 11 开始的这让我们很难受,所以:

i=1nj=i+1nlcm(ai,aj)=i=1nj=1nlcm(ai,aj)i=1nai2\sum_{i=1}^{n}\sum_{j=i+1}^{n}\mathrm{lcm}(a_i,a_j)=\frac{\sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)-\sum_{i=1}^{n}{a_i}}{2}

现在我们的就是要算 i=1nj=1nlcm(ai,aj)\displaystyle \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)

i=1nj=1nlcm(ai,aj)=i=1nj=1nai×ajgcd(ai,aj)=i=1nj=1nd=1Maxai×ajd[gcd(ai,aj)=d]\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{i=1}^{n}\sum_{j=1}^{n}{\frac{a_i \times a_j}{\gcd(a_i,a_j)}} \\ &=\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{d=1}^{Max}{\frac{a_i \times a_j}{d}[\gcd(a_i,a_j)=d]} \end{aligned}

注意到可以把后面的 \sum 提到前面:

i=1nj=1nlcm(ai,aj)=i=1nj=1nd=1Maxai×ajd[gcd(ai,aj)=d]=d=1Max1di=1nj=1nai×aj×[gcd(ai,aj)=d]\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{i=1}^{n}\sum_{j=1}^{n}\sum_{d=1}^{Max}{\frac{a_i \times a_j}{d}[\gcd(a_i,a_j)=d]} \\ &=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [\gcd(a_i,a_j)=d]} \end{aligned}

我们注意到 [gcd(ai,aj)=d][\gcd(a_i,a_j)=d] 这个式子,这个时候我们想到了什么?没错,莫比乌斯反演!

[k=1]=dkμ(d)[k=1]=\sum_{d|k}\mu(d)

但是 [gcd(ai,aj)=d][\gcd(a_i,a_j)=d] 这个式子,后面的是 dd 而不是 11 ,那我们就把式子变一下形。

[gcd(ai,aj)=d][dai][daj]=[gcd(aid,ajd)=1][dai][daj][\gcd(a_i,a_j)=d][d|a_i][d|a_j]=[\gcd(\frac{a_i}{d},\frac{a_j}{d})=1][d|a_i][d|a_j]

因为我们注意到 dai,dajd|a_i,d|a_j 所以就有上面的转化。

i=1nj=1nlcm(ai,aj)=d=1Max1di=1nj=1nai×aj×[gcd(ai,aj)=d]=d=1Max1di=1nj=1nai×aj×[dai][daj][gcd(aid,ajd)=1]\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [\gcd(a_i,a_j)=d]} \\ &=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j][\gcd(\frac{a_i}{d},\frac{a_j}{d})=1]} \end{aligned}

之后进行反演

i=1nj=1nlcm(ai,aj)=d=1Max1di=1nj=1nai×aj×[dai][daj][gcd(aid,ajd)=1]=d=1Max1di=1nj=1nai×aj×[dai][daj]tgcd(aid,ajd)μ(t)\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j][\gcd(\frac{a_i}{d},\frac{a_j}{d})=1]} \\ &=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j]\sum_{t|\gcd(\frac{a_i}{d},\frac{a_j}{d})}}{\mu(t)} \end{aligned}

注意到可以和上面一样,所以我们也把 tt 的求和往前提。

i=1nj=1nlcm(ai,aj)=d=1Max1di=1nj=1nai×aj×[dai][daj]tgcd(aid,ajd)μ(t)=d=1Maxt=1Maxdμ(t)di=1nj=1nai×aj×[dai][daj][tai][taj]=d=1Maxt=1Maxdμ(t)di=1nj=1nai×aj×[dtai][dtaj]\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{d=1}^{Max}\frac{1}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j]\sum_{t|\gcd(\frac{a_i}{d},\frac{a_j}{d})}}{\mu(t)} \\ &=\sum_{d=1}^{Max}\sum_{t=1}^{\lfloor \frac{Max}{d} \rfloor}\frac{\mu(t)}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j][t|a_i][t|a_j]} \\ &=\sum_{d=1}^{Max}\sum_{t=1}^{\lfloor \frac{Max}{d} \rfloor}\frac{\mu(t)}{d}\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [dt|a_i][dt|a_j]} \end{aligned}

我们来观察后面这个式子 i=1nj=1nai×aj×[dai][daj]\displaystyle \sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [d|a_i][d|a_j]} ,对于任何一个 dad|a 都会对任何一个 dBd|B

注意到 (i=1kai)2\displaystyle (\sum_{i=1}^{k}a_i)^2 刚好就是 ax(x[1,k])a_x (x \in [1,k]) 对于所有 ay(y[1,k])a_y(y \in [1,k]) 都有贡献,所以:

i=1nj=1nai×aj×[dtai][dtaj]=(i=1nai×[dtai])2\sum_{i=1}^{n}\sum_{j=1}^{n}{a_i\times a_j\times [dt|a_i][dt|a_j]}=(\sum_{i=1}^{n}a_i\times [dt|a_i])^2

i=1nj=1nlcm(ai,aj)=d=1Maxt=1Maxdμ(t)d(i=1nai×[dtai])2\begin{aligned} \sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)&=\sum_{d=1}^{Max}\sum_{t=1}^{\lfloor \frac{Max}{d} \rfloor}\frac{\mu(t)}{d}(\sum_{i=1}^{n}a_i\times [dt|a_i])^2 \end{aligned}

我们发现 aia_i 的值域只有 10610^6 ,所以我们可以用 cic_i 表示有多少个 ii,这样就有:

i=1nai×[dtai]=dtiMaxi×ci\sum_{i=1}^{n}a_i\times [dt|a_i]=\sum_{dt|i}^{Max}i\times c_i

TiMaxi×ci\displaystyle \sum_{T|i}^{Max}i\times c_i显然可以用类似筛法的一个东西用 O(nlog(n))O(nlog(n))的方法求出对于每一个 TT 的值。

现在我们的式子变成了:

i=1nj=1nlcm(ai,aj)=d=1Maxt=1Maxdμ(t)d(dtiMaxi×ci)2\sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j)=\sum_{d=1}^{Max}\sum_{t=1}^{\lfloor \frac{Max}{d} \rfloor}\frac{\mu(t)}{d}(\sum_{dt|i}^{Max}i\times c_i)^2

那么我们只需要枚举 dd 再枚举 tt 就可以利用 O(nlog(n))O(nlog(n)) 的时间算出答案。

既然我们已经计算出了 i=1nj=1nlcm(ai,aj)\sum_{i=1}^{n}\sum_{j=1}^{n}\mathrm{lcm}(a_i,a_j) 的值,我们把它减去 i=1nai\sum_{i=1}^{n}{a_i} ,再除 22(这里取模的话就要用一下逆元),就可以算出 kk 了。

kk 的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 998244353;
bool isp[1000000 + 10];
vector<int>prm;
ll n, cnt[1000000 + 5], ans, mu[1000000 + 10], f[1000000 + 10], g[1000000 + 10];
void getprm(int lim) {
memset(isp, 1, sizeof isp);
isp[0] = isp[1] = 0;
mu[1] = 1;
for (int i = 2; i <= lim; ++i) {
if (isp[i])
prm.push_back(i),
mu[i] = -1;
for (int j = 0; j < prm.size(); ++j) {
if (i * prm[j] > lim) break;
isp[i * prm[j]] = 0;
if (i % prm[j] == 0) break;
mu[i * prm[j]] = -mu[i];
}
}
for (ll i = 1; i <= 1000000; i++)
for (ll j = i; j <= 1000000; j += i)
f[j] += mu[i] * i;
for (ll i = 1; i <= 1000000; i++) {
for (ll j = 1; j <= 1000000 / i; j++)
(g[i] += j * cnt[j * i]) %= mod;
}
}
ll poww(ll x, ll k) {
if (k == 0) return 1;
if (k == 1) return x;
ll tmp = poww(x, k / 2);
tmp = (tmp * tmp) % mod;
if (k % 2 == 1) return tmp * x % mod;
else return tmp;
}
int main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n;
for (ll i = 1, x; i <= n; i++)
cin >> x, ++cnt[x];
getprm(1000000);
for (ll i = 1; i <= 1000000; i++)
(ans += i * g[i] % mod * g[i] % mod * f[i]) %= mod;
for (ll i = 1; i <= 1000000; i++)
if (cnt[i])
(ans -= i * cnt[i]) %= mod;
((ans %= mod) += mod) %= mod;
(ans *= poww(2, mod - 2)) %= mod;
cout << ans << endl;
}

f(k)f(k)kk 各个位数上的和,我们要求的 ansans 满足 kansk|ansf(ans)f(ans) 最小

考虑 dpidp_i 表示 minf(x)(xi(modk))\min {f(x)}(x\equiv i\pmod k)

怎么转移?注意到可以在 x\ x ( xi(modk))(\ x \equiv i\pmod k) 后加上一个数 y(y[0,9]),y(y \in [0,9]), 那么易得加上后的余数为 (x×10+y)modk(x\times 10+y) \mod k(i×10+y)modk(i\times 10+y)\mod k,所以 dp[(i×10+y)modk]=min(dp[i]+y)dp[(i\times 10+y)\mod k] = \min (dp[i]+y)

注意到这个式子和图的松弛式子很像,接下去就建图确定转移顺序,再跑一遍单源最短路径板子即可,答案即 dis[0]dis[0],边是 kk1010 倍,复杂度为O(klog2k)\mathcal{O(k\log_{2} k)}

代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int mod = 3999971;
bool isp[1000000 + 10];
vector<int>prm;
ll n, cnt[1000000 + 5], ans, mu[1000000 + 10], f[1000000 + 10], g[1000000 + 10];
void getprm(int lim) {
memset(isp, 1, sizeof isp);
isp[0] = isp[1] = 0;
mu[1] = 1;
for (int i = 2; i <= lim; ++i) {
if (isp[i])
prm.push_back(i),
mu[i] = -1;
for (int j = 0; j < prm.size(); ++j) {
if (i * prm[j] > lim) break;
isp[i * prm[j]] = 0;
if (i % prm[j] == 0) break;
mu[i * prm[j]] = -mu[i];
}
}
for (ll i = 1; i <= 1000000; i++)
for (ll j = i; j <= 1000000; j += i)
f[j] += mu[i] * i;
for (ll i = 1; i <= 1000000; i++) {
for (ll j = 1; j <= 1000000 / i; j++)
(g[i] += j * cnt[j * i]) %= mod;
}
}
ll poww(ll x, ll k) {
if (k == 0) return 1;
if (k == 1) return x;
ll tmp = poww(x, k / 2);
tmp = (tmp * tmp) % mod;
if (k % 2 == 1) return tmp * x % mod;
else return tmp;
}
namespace Change {
struct Edge {
int v, w, nxt;
}edge[40000000 + 5];
int head[4000000 + 5], idx;
void add(int u, int v, int w) {
edge[++idx] = { v,w,head[u] };
head[u] = idx;
}
struct node {
int first, second;
friend bool operator<(const node& a, const node& b) {
return a.first > b.first;
}
};
int n, m, k, dis[4000000 + 5];
priority_queue<node>q;
bool vis[4000000 + 5];
void dij() {
memset(dis, 0x3f, sizeof dis);
dis[k] = 0;
q.push({ 0,k });
while (!q.empty()) {
node p = q.top(); q.pop();
if (vis[p.second]) continue;
vis[p.second] = 1;
for (int i = head[p.second]; i; i = edge[i].nxt) {
if (dis[edge[i].v] > dis[p.second] + edge[i].w) {
dis[edge[i].v] = dis[p.second] + edge[i].w;
q.push({ dis[p.second] + edge[i].w,edge[i].v });
}
}
}
}
void main(int k) {
for (int i = 0; i < k; ++i)
for (int j = 0; j < 10; ++j)
add(i, (i * 10 + j) % k, j);
for (int i = 1; i < 10; ++i)
add(k, i % k, i);
dij();
cout << dis[0] << endl;
}
}
int main() {
cin.tie(0)->sync_with_stdio(false);
cin >> n;
for (ll i = 1, x; i <= n; i++)
cin >> x, ++cnt[x];
getprm(1000000);
for (ll i = 1; i <= 1000000; i++)
(ans += i * g[i] % mod * g[i] % mod * f[i]) %= mod;
for (ll i = 1; i <= 1000000; i++)
if (cnt[i])
(ans -= i * cnt[i]) %= mod;
((ans %= mod) += mod) %= mod;
(ans *= poww(2, mod - 2)) %= mod;
Change::main(ans);
return 0;
}

name 题解
https://www.lzj-blog.top/2025/02/13/name 题解/
作者
lzj
发布于
2025年2月13日
许可协议