加载中...

4.13——911D(gcd+容斥 经典trick)

911D

限时每日一题day29。很典的一个 \(gcd\) 容斥经典 \(trick\),之前 VP 的时候还做过一个类似的题,可惜没做出来。

不难想到可以排序后再计算贡献。此时答案可以简化为:

\[\sum_{i=1}^{n-1}\sum_{j=i+1}^{n}(n - j)\times gcd(a_{i},a_{j}) \]

可以枚举 \(j\),然后再枚举 \(a_{j}\) 的所有约数 \(x\),统计有多少个 \(a_{i}\) 满足 \(gcd(a_{i},a_{j}) = x\)

\(f[x]\)\(gcd(a_{i},a_{j}) = x\)\(a_{i}\) 数量。

\(f[x]\) 计算式为:

\[f[x] = cnt[x] - \sum_{k=2}^{\inf}f[kx] \]

其中 \(cnt[x]\) 表示序列 \(a\) 中为 \(x\) 的倍数的元素个数。

原理:

\[cnt[x] = f[x] + f[2x] + f[3x] + ... \]

一般可以通过倒序枚举约数来加速递推计算。感觉这个 \(trick\) 使用时较为灵活,所以这里就不过多总结了。

本题的做法为:枚举每个 \(a[j]\) 时,计算对应的 \(f[x]\),其中 \(x\)\(a[j]\) 的约数。初始时令 \(f[x]\) = \(cnt[x]\),倒序枚举 \(a[j]\) 的所有约数,计算出较大 \(x\)\(f[x]\) 后,再枚举 \(x\) 的所有约数 \(xx\),对于每个 \(f[xx]\) 容斥掉 \(f[x]\)。复杂度大概为 \(O(nlog^{2}m)\)。具体细节见代码。

code

posted @ 2025-04-13 10:55  jxs123  阅读(20)  评论(0)    收藏  举报