华中农业大学第十三届程序设计竞赛
B
syh 喜欢猫猫,所以 zzy 为了哄 syh 睡觉,决定扮成猫猫。
给定一个长为 \(n\) 的序列 \(\{a_i\}\) 和三个正整数 \(x,y,z\),计算 \(\sum_{i=1}^n\sum_{j=1}^n a_ia_j\lfloor \dfrac{x\gcd(a_i,a_j)+y}{z} \rfloor\) 的值。答案对 \(10^9+7\) 取模。
如果这个问题的答案能够被正确解出,zzy 就会学猫叫。由于 zzy 正在学怎么学猫叫,所以请你告诉 syh 这个问题的答案。
赛时想到枚举 \(a[i]\) , 去找它的因子最为 \(gcd \ k\) , 再求\(\sum a_j\) (其中 \(gcd(a_i , a_j) = k\)).
将因子 \(k\) 从大到小枚举,这个 \(k\) 带来的 \(\sum aj\) 可以预处理,不过要减去它在各个因子集合中倍数带来的 \(\sum a_j\) 影响。
在枚举因子 \(k\) 倍数的时候就卡住了。
看了看榜一佬的思想,他把 \(a[i] * a[j]\) 整体看成了答案.
\(f[k]\) 代表 \(gcd = k\) 时,\(\sum a[i] * a[j]\).
之后就是类似于我们赛事的那个容斥思想了 (\(f[k]\) 不好求 , 求\(f[k >= i] - f[k > i]\))
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
const int N = 1E5 + 5;
const int mod = 1E9 + 7;
int n;
int num[N];
int f[N];
void solve() {
cin >> n;
LL x , y , z;
cin >> x >> y >> z;
for (int i = 1 ; i <= n ; ++i) {
int ai;
cin >> ai;
(num[ai] += ai) %= mod;
}
for (int i = 1 ; i < N ; ++i) {
for (int j = i ; j < N ; j += i) {
(f[i] += num[j]) %= mod;
}
}
for (int i = N - 1 ; i >= 1 ; --i) {
f[i] = 1LL * f[i] * f[i] % mod;
for (int j = i + i ; j < N ; j += i) {
f[i] -= f[j];
f[i] = (f[i] % mod + mod) % mod;
}
}
LL ans = 0;
for (int i = 1 ; i < N ; ++i) {
ans += 1LL * f[i] * ((x * i + y) / z) % mod;
ans %= mod;
}
cout << ans << '\n';
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int T = 1;
while (T--) {
solve();
}
return 0;
}

浙公网安备 33010602011771号