题目链接

LOJ2476:https://loj.ac/problem/2476

LOJ2565:https://loj.ac/problem/2565

题解

参考照搬了 wxh 的博客

为了方便,下文用 \((x, y)\) 表示 \({\rm gcd}(x, y)\)。

先分析 LOJ2476。

注意到对于任意一个数组 \(a\),第 \(x\) 项的值 \(a_x\) 可以展开写成 \(\sum_\limits{i = 1}^{x} a_i[i = x]\),进一步地,有:

\[\begin{aligned}a_x &= \sum_{i = 1}^{x} a_i [i = x] \\ &= \sum_{i | x}a_i[\frac{x}{i} = 1] \\ &= \sum_{i |x} a_i \sum_{p | \frac{x}{i}} \mu (p) \\ &= \sum_{p |x} \sum_{i | p} a_i \mu(\frac{p}{i}) \\ &= \sum_{p |x} (a * \mu)(p) \end{aligned}
\]

对于数组 \(a\),不妨设 \(f(a) = a * \mu\),那么原式等于:

\[\begin{aligned}\sum_{k = 1}^n C_k \sum_{i = 1}^n \sum_{j = 1}^n A_iB_j D_{(i, j)} \sum_{p | (i, k)} f(E)(p)\sum_{q | (j, k)}\end{aligned} f(F)(q)
\]

令 \(g(a)(x) = \sum_\limits{x | i}a_i\),原式等于:

\[\begin{aligned}&\sum_{{\rm lcm}(p, q) \leq n} f(E)(p) \times f(F)(q) \times g(C)({\rm lcm}(p, q)) \sum_{ip \leq n}A_{ip} \sum_{jq \leq n}B_{jq} D_{(ip, jq)} \\ =& \sum_{d = 1}^n \sum_{xy \leq \left\lfloor\frac{n}{d}\right\rfloor, (x, y) = 1} f(E)(xd) \times f(F)(yd) \times g(C)(xyd)\sum_{ix \leq \left\lfloor\frac{n}{d}\right\rfloor} \sum_{jy \leq \left\lfloor\frac{n}{d}\right\rfloor} A_{ixd} B_{jyd} D_{d \times (ix, jy)}\end{aligned}
\]

当 \(d\) 已知时,令 \(P_i = f(E)(id), Q_i = f(F)(id), R_i = g(C)(id), S_i = A_{id}, T_i = B_{id}, W_i = D_{id}\)。设 \(m = \left\lfloor\frac{n}{d}\right\rfloor\),原式等于:

\[\begin{aligned} \sum_{d = 1}^n \sum_{xy \leq m, (x, y) = 1} P_x Q_y R_{xy} \sum_{ix \leq m} \sum_{jy \leq m} S_{ix} T_{jy} W_{(ix, jy)} \end{aligned}
\]

对于每个 \(d\),我们可以先预处理出数组 \(P, Q, R, S, T, W\)。这样,如果 \(x\) 与 \(y\) 也已知,那么 \(P_xQ_yR_{xy}\) 可以直接得到。考虑如何求后面的部分:

\[\begin{aligned} &\sum_{ix \leq m} \sum_{jy \leq m} S_{ix} T_{jy} W_{(ix, jy)} \\ = & \sum_{ix \leq m} S_{ix} \sum_{jy \leq m} T_{jy} \sum_{r | (ix, jy)} f(W)(r) \\ = & \sum_{jy \leq m} T_{jy} \sum_{r | jy} f(W)(r) \sum_{r | ix} S_{ix}\end{aligned}
\]

设 \(u = ix, v= jy\),那么上式等于:

\[\begin{aligned}\sum_{y | v} T_{v} \sum_{r | v} f(W)(r) \sum_{ r | u} [x | u]S_{u}\end{aligned}
\]

令 \(h(a)(x) = \sum_\limits{i | x} a_i\),那么上式可以从右往左依次计算,具体地,令函数 \(f_1(u) = [x | u]S_{u}\),那么我们可以先计算 \(g(f_1)\) 来得到每一个 \(r\) 对应的 \(\sum_\limits{r | u}[x | u]S_{u}\),再令函数 \(f_2(r) = f(W)(r) \times g(f_1)(r)\),那么我们可以计算 \(h(f_2)\) 来得到每一个 \(v\) 对应的 \(\sum_\limits{r | v} f(W)(r) \sum_\limits{r | u} [x | u]S_{u}\)。这样,上式即为枚举所有 \(y\) 的倍数 \(v\),求 \(T_{v} \times h(f_2)(v)\)。

先忽略所有求 \(f(a), g(a), h(a)\) 等函数的复杂度。首先我们需要枚举 \(d\)。对于每一个 \(d\),我们需要暴力枚举所有可能的 \(x, y\),对于每一组合法的 \(x, y\)(即满足 \(xy \leq m, (x, y) = 1\)),再暴力枚举不超过 \(m\) 的 \(y\) 的倍数。经程序验证,当 \(n = 10^5\) 时,总枚举量为 \(98380871\),在可接受的范围内。

对于一个长度为 \(n\) 的数组 \(a\),求 \(f(a)\) 的时间复杂度为 \(O(n \log n)\),求 \(g(a)\) 与 \(h(a)\) 的时间复杂度均为 \(O(n \log \log n)\)。首先,我们需要预处理出 \(f(E), f(F)\) 与 \(g(C)\),时间复杂度为 \(O(n \log n)\)。 对于每一个 \(d\),我们需要求出 \(P, Q, R, S, T, W\) 与 \(f(W)\),时间复杂度为 \(O(m \log m)\)。当 \(d\) 确定时,对于每一个 \(x\),我们需要求出 \(f_1, g(f_1), f_2, h(f_2)\),由于 \(x \leq \sqrt m\),因此时间复杂度为 \(O(m \sqrt m \log \log m)\)。

最终时间复杂度为 \(O(n \log n)+ \sum_\limits{i = 1}^n O\left( \left(\frac{n}{i}\right) \log \left(\frac{n}{i}\right) + \left(\frac{n}{i}\right)^{1.5} \log \log\left(\frac{n}{i}\right)\right)\) \(= O(n \sqrt n \log \log n)\)。

接下来分析 LOJ2565。

首先有 \(d(ijk) = \sum_\limits{x |i}\sum_\limits{y | j}\sum_\limits{z | k}[(x, y) = 1][(y, z) = 1][(x, z) = 1]\)。证明如下:

令 \(s = ijk\)。分别写出 \(i, j, k, s\) 的唯一分解式:

\[\begin{aligned}i &= p_1^{a_1}p_2^{a_2} \cdots p_t^{a_t} \\j &= p_1^{b_1}p_2^{b_2} \cdots p_t^{b_t} \\ k &= p_1^{c_1}p_2^{c_2} \cdots p_t^{c_t} \\ s &= p_1^{a_1 + b_1 + c_1}p_2^{a_2 + b_2 + c_2} \cdots p_t^{a_t + b_t + c_t}\end{aligned}
\]

那么 \(d(ijk) = \prod_\limits{r = 1}^t(a_r + b_r + c_r + 1)\)。

考虑计算 \(\sum_\limits{x |i}\sum_\limits{y | j}\sum_\limits{z | k}[(x, y) = 1][(y, z) = 1][(x, z) = 1]\) 的值。不难发现,满足 \(x | i, y | j, z | k\) 且 \((x, y) = 1, (y, z) = 1, (x, z) = 1\) 的 \(x, y, z\) 必然有:\(\forall r(1 \leq r \leq t)\),\(x, y, z\) 中至少有两个数满足其唯一分解式中 \(p_r\) 的指数为 \(0\)。当 \(x, y, z\) 中至少有两个数满足其唯一分解式中 \(p_r\) 的指数为 \(0\) 时,\(x, y, z\) 三个数的唯一分解式中 \(p_r\) 的指数共有 \(a_r + b_r + c_r + 1\) 种情况。显然,对于各个 \(r\),情况是独立的,因此根据乘法原理,满足 \(x | i, y | j, z | k\) 且 \((x, y) = 1, (y, z) = 1, (x, z) = 1\) 的 \(x,y, z\) 共有 \(\prod_\limits{r = 1}^t (a_r + b_r + c_r + 1)\) 组。其数量恰好等于 \(d(ijk)\) 的值。

将 \(d(ijk) = \sum_\limits{x |i}\sum_\limits{y | j}\sum_\limits{z | k}[(x, y) = 1][(y, z) = 1][(x, z) = 1]\) 代入原式得:

\[\begin{aligned} \sum_{i = 1}^A \sum_{j = 1}^B \sum_{k = 1}^C d(ijk) &= \sum_{i = 1}^A \sum_{j = 1}^B \sum_{k = 1}^C \sum_{x | i} \sum_{y | j}\sum_{z|k} [(x, y) = 1][(y, z) = 1][(x, z) = 1] \\ &= \sum_{x = 1}^A \sum_{y = 1}^B \sum_{z = 1}^C [(x, y) = 1][(y, z) = 1][(x, z) = 1]\left\lfloor\frac{A}{x}\right\rfloor \left\lfloor\frac{B}{y}\right\rfloor \left\lfloor\frac{C}{z}\right\rfloor\end{aligned}
\]

定义函数 \(a_i = \left\lfloor\frac{A}{i}\right\rfloor, b_i = \left\lfloor\frac{B}{i}\right\rfloor, c_i = \left\lfloor\frac{C}{i}\right\rfloor, f_i = [i = 1]\)。那么原式即为:

\[\sum_{x = 1}^A \sum_{y = 1}^B \sum_{z = 1}^C a_x b_y c_z f_{(x, y)}f_{(y, z)}f_{(x, z)}
\]

至此,我们得到了和上题形式完全一样的式子。因此直接套用上题做法即可。单组数据的时间复杂度不变。不过有点卡常,因为本题的正解压根就不是这个。

代码

LOJ2476 代码如下:

#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10;

unsigned long long a[N], b[N], c[N], d[N], e[N], f[N], p[N], q[N], r[N], s[N], t[N], w[N], u[N], v[N];
int n, primes[N], all;
bool is_prime[N]; void F(unsigned long long* a, int n) {
for (int i = 1; i <= n; ++i) {
for (int j = i + i; j <= n; j += i) {
a[j] -= a[i];
}
}
} void G(unsigned long long* a, int n) {
for (int i = 1; i <= all && primes[i] <= n; ++i) {
for (int j = n / primes[i]; j; --j) {
a[j] += a[j * primes[i]];
}
}
} void H(unsigned long long* a, int n) {
for (int i = 1; i <= all && primes[i] <= n; ++i) {
for (int j = 1; j * primes[i] <= n; ++j) {
a[j * primes[i]] += a[j];
}
}
} void sieve(int n) {
fill(is_prime + 1, is_prime + 1 + n, true);
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) {
primes[++all] = i;
}
for (int j = 1; j <= all; ++j) {
if (primes[j] * i > n) {
break;
}
is_prime[primes[j] * i] = false;
if (i % primes[j] == 0) {
break;
}
}
}
} 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]);
}
sieve(n);
F(e, n);
F(f, n);
G(c, n);
unsigned long long answer = 0;
for (int i = 1; i <= n; ++i) {
int m = n / i;
for (int j = 1; j <= m; ++j) {
p[j] = e[j * i];
q[j] = f[j * i];
r[j] = c[j * i];
s[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) {
fill(u + 1, u + 1 + m, 0);
fill(v + 1, v + 1 + m, 0);
for (int j = x; j <= m; j += x) {
u[j] = s[j], v[j] = t[j];
}
G(u, m);
G(v, m);
for (int j = 1; j <= m; ++j) {
u[j] *= w[j];
v[j] *= w[j];
}
H(u, m);
H(v, m);
for (int j = 1; j <= m; ++j) {
u[j] *= t[j];
v[j] *= s[j];
}
for (int y = x; x * y <= m; ++y) {
if (__gcd(x, y) == 1) {
unsigned long long s1 = 0, s2 = 0;
for (int j = y; j <= m; j += y) {
s1 += u[j];
s2 += v[j];
}
answer += s1 * p[x] * q[y] * r[x * y];
if (x != y) {
answer += s2 * p[y] * q[x] * r[x * y];
}
}
}
}
}
printf("%llu\n", answer);
return 0;
}

LOJ2565 代码如下:

#include<bits/stdc++.h>

using namespace std;

const int N = 1e5 + 10, mod = 1e9 + 7;

void add(int& x, int y) {
x += y;
if (x >= mod) {
x -= mod;
}
} void sub(int& x, int y) {
x -= y;
if (x < 0) {
x += mod;
}
} template<typename T>
int mul(T x) {
return x;
} template<typename T, typename... R>
int mul(T x, R... y) {
return (long long) x * mul(y...) % mod;
} int tt, A, B, C, a[N], b[N], c[N], d[N], e[N], f[N], p[N], q[N], r[N], s[N], t[N], w[N], u[N], v[N], primes[N], all;
bool is_prime[N]; void F(int* a, int n) {
for (int i = 1; i <= n; ++i) {
for (int j = i + i; j <= n; j += i) {
sub(a[j], a[i]);
}
}
} void G(int* a, int n) {
for (int i = 1; i <= all && primes[i] <= n; ++i) {
for (int j = n / primes[i]; j; --j) {
add(a[j], a[j * primes[i]]);
}
}
} void H(int* a, int n) {
for (int i = 1; i <= all && primes[i] <= n; ++i) {
for (int j = 1; j * primes[i] <= n; ++j) {
add(a[j * primes[i]], a[j]);
}
}
} void sieve(int n) {
fill(is_prime + 1, is_prime + 1 + n, true);
all = 0;
for (int i = 2; i <= n; ++i) {
if (is_prime[i]) {
primes[++all] = i;
}
for (int j = 1; j <= all; ++j) {
if (primes[j] * i > n) {
break;
}
is_prime[primes[j] * i] = false;
if (i % primes[j] == 0) {
break;
}
}
}
} int main() {
scanf("%d", &tt);
while (tt--) {
scanf("%d%d%d", &A, &B, &C);
int n = max(A, max(B, C));
sieve(n);
for (int i = 1; i <= n; ++i) {
a[i] = A / i;
b[i] = B / i;
c[i] = C / i;
d[i] = e[i] = f[i] = (i == 1);
}
F(e, n);
F(f, n);
G(c, n);
int answer = 0;
for (int i = 1; i <= n; ++i) {
int m = n / i;
for (int j = 1; j <= m; ++j) {
p[j] = e[j * i];
q[j] = f[j * i];
r[j] = c[j * i];
s[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) {
fill(u + 1, u + 1 + m, 0);
fill(v + 1, v + 1 + m, 0);
for (int j = x; j <= m; j += x) {
u[j] = s[j], v[j] = t[j];
}
G(u, m);
G(v, m);
for (int j = 1; j <= m; ++j) {
u[j] = mul(u[j], w[j]);
v[j] = mul(v[j], w[j]);
}
H(u, m);
H(v, m);
for (int j = 1; j <= m; ++j) {
u[j] = mul(u[j], t[j]);
v[j] = mul(v[j], s[j]);
}
for (int y = x; x * y <= m; ++y) {
if (__gcd(x, y) == 1) {
int s1 = 0, s2 = 0;
for (int j = y; j <= m; j += y) {
add(s1, u[j]);
add(s2, v[j]);
}
add(answer, mul(s1, p[x], q[y], r[x * y]));
if (x != y) {
add(answer, mul(s2, p[y], q[x], r[x * y]));
}
}
}
}
}
printf("%d\n", answer);
}
return 0;
}

LOJ2476. 「2018 集训队互测 Day 3」蒜头的奖杯 & LOJ2565. 「SDOI2018」旧试题(莫比乌斯反演)的更多相关文章

  1. 【LOJ2461】「2018 集训队互测 Day 1」完美的队列(分块+双指针)

    点此看题面 大致题意: 让你维护\(n\)个有限定长度的队列,每次区间往队列里加数,求每次加完后的队列里剩余元素种类数. 核心思路 这道题可以用分块+双指针去搞. 考虑求出每个操作插入的元素在队列中被 ...

  2. @loj - 2461@ 「2018 集训队互测 Day 1」完美的队列

    目录 @description@ @solution@ @part - 0@ @part - 1@ @accepted code@ @details@ @description@ 小 D 有 n 个 ...

  3. 【loj2461】【2018集训队互测Day 1】完美的队列

    #2461. 「2018 集训队互测 Day 1」完美的队列 传送门: https://loj.ac/problem/2461 题解: 直接做可能一次操作加入队列同时会弹出很多数字,无法维护:一个操作 ...

  4. 【2018集训队互测】【XSY3372】取石子

    题目来源:2018集训队互测 Round17 T2 题意: 题解: 显然我是不可能想出来的……但是觉得这题题解太神了就来搬(chao)一下……Orzpyz! 显然不会无解…… 为了方便计算石子个数,在 ...

  5. LOJ3069. 「2019 集训队互测 Day 1」整点计数(min_25筛)

    题目链接 https://loj.ac/problem/3069 题解 复数真神奇. 一句话题意:令 \(f(x)\) 表示以原点 \((0, 0)\) 为圆心,半径为 \(x\) 的圆上的整点数量, ...

  6. [JZOJ6088] [BZOJ5376] [loj #2463]【2018集训队互测Day 1】完美的旅行【线性递推】【多项式】【FWT】

    Description Solution 我们考虑将问题一步步拆解 第一步求出\(F_{S,i}\)表示一次旅行按位与的值为S,走了i步的方案数. 第二步答案是\(F_{S,i}\)的二维重复卷积,记 ...

  7. 洛谷 P4463 - [集训队互测 2012] calc(多项式)

    题面传送门 & 加强版题面传送门 竟然能独立做出 jxd 互测的题(及其加强版),震撼震撼(((故写题解以祭之 首先由于 \(a_1,a_2,\cdots,a_n\) 互不相同,故可以考虑求出 ...

  8. EZ 2018 05 06 NOIP2018 慈溪中学集训队互测(五)

    享受爆零的快感 老叶本来是让初三的打的,然后我SB的去凑热闹了 TM的T2写炸了(去你妹的优化),T1连-1的分都忘记判了,T3理所当然的不会 光荣革命啊! T1 思维图论题,CHJ dalao给出了 ...

  9. 【纪中集训2019.3.27】【集训队互测2018】小A的旅行(白)

    题目 描述 ​ \(0-n-1\)的图,满足\(n\)是\(2\)的整数次幂, $ i \to j $ 有 $ A_{i,j} $ 条路径: ​ 一条路径的愉悦值定义为起点和终点编号的\(and\)值 ...

随机推荐

  1. 11 Mortal Fibonacci Rabbits

    Problem Figure 4. A figure illustrating the propagation of Fibonacci's rabbits if they die after thr ...

  2. js去掉字符串前后空格的五种方法(转)

    出处:http://www.2cto.com/kf/201204/125943.html 第一种:循环检查替换[javascript]//供使用者调用  function trim(s){  retu ...

  3. linux nkf 日文编码转换命令[转载]

    对于日语的编码 windows : Shift-JIS Linux : 2.4内核使用EUC编码,2.6内核中使用UTF8编码 检查文件编码  nkf -g filename 通常处理字符编码都使用i ...

  4. 看图说说class文件结构(部分)

  5. 服务器如何打开ping命令

    服务器禁止ping后忘记是用什么方法禁止的了.只知道不是使用ip策略现在需要再开启ping...请问该怎么弄? 是不是windows防火墙开启了啊,到控制面板里的windows防火墙中看看,把防火墙关 ...

  6. ZOJ3703 Happy Programming Contest 2017-04-06 23:33 61人阅读 评论(0) 收藏

    Happy Programming Contest Time Limit: 2 Seconds      Memory Limit: 65536 KB In Zhejiang University P ...

  7. .NET 匿名方法的BUG,请专家解答

    匿名方法是.NET 3.5之后的一个好东东,很多人使用,但是我在最近的工作当中发现了一个问题. 请专家解答 //list里存放10个数字 List<); ; i < ; i++) { li ...

  8. Javascript几个时髦的hack技巧《Javascript Hacks for Hipsters》

    转自:http://berzniz.com/post/68001735765/javascript-hacks-for-hipsters Javascript Hacks for Hipsters J ...

  9. 如何为SharePoint文档库、文件夹、文件单独设置权限

    在这里使用截图的方式简单描述两个问题:设置SharePoint Server文档库权限和文档库中的文件夹权限 一.设置SharePoint Server文档库权限 Figure 1 - 打开文档库后, ...

  10. TFS 2015新功能之一,当前迭代查询标记

    TFS 2015发布在即,有幸作为MVP提前获得了TFS的RTM版本,下面就TFS 2015的新功能做一些介绍:   TFS 2015新功能之一,当前迭代查询标记 在TFS的查询中,可以将" ...