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)\)。具体细节见代码。