题目链接:https://codeforces.com/contest/1436/problem/F
题目大意:
一个多重集 (S),有 (m) 种不同的数,第 (i) 种数为 (a_i),有 (freq_i) 个。
求满足如下条件的和式 (∑x∈A∑y∈Bxy∑x∈A∑y∈Bxy) 的值:
[B⊂A
]
[|B|=|A|−1|B|=|A|−1
]
[gcdx∈A{x}=1
]
注意,其中 (A,B) 也为多重集。
涉及 (gcd) 的式子一般可以用套路莫比乌斯反演
设 (f(i)) 为 (gcd) 为 (i) 时的答案
很难直接算
于是另 (g(i) = sum_{i mid d} mu(frac{d}{i})f(d))
答案就是 $$f(1) = sum_{i = 1}^n mu(i)g(i)$$
考虑计算 (g(i)), 将所有 (i) 的倍数找出来放到一个集合中,计算这个集合的答案
设该集合大小为 (k), 考虑每一对 (a_i * a_j) 的贡献,
当x和y是同一个数的时候,贡献是 (x^2(k−1)2^{k-2}freq[x])
当x和y数值相同但不是同一个数的时候,贡献是 (x^2[(k−2)2^{k-3}+2^{k−2}]freq[x](freq[x]−1))
当x不等于y的时候,贡献是 (xy[(k−2)2^{k-3}+2^{k−2}]freq[x]freq[y])
(上述公式是考虑 (B) 是由 (A) 删去了哪个数得出的)
(x, y) 不相等的情况还是无法直接枚举,发现 (y) 一定是 (i) 的倍数,所以推一下式子用前缀和优化一下即可
注意: 取模一定要仔细
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int maxn = 100010;
const ll M = 998244353;
const int N = 100000;
int n, m;
ll ans;
ll a[maxn], c[maxn];
int is[maxn], prime[maxn], mu[maxn], cnt = 0;
ll qsm(ll i, ll po){
ll res = 1;
while(po){
if(po & 1) res = 1ll * res * i % M;
po >>= 1;
i = 1ll * i * i % M;
}
return res;
}
vector<P> v;
ll read(){ ll s = 0, f = 1; char ch = getchar(); while(ch < '0' || ch > '9'){ if(ch == '-') f = -1; ch = getchar(); } while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); } return s * f; }
int main(){
ll inv = qsm(2, M - 2);
m = read();
for(int i = 1 ; i <= m ; ++i) {
a[i] = read(), c[a[i]] = read();
}
mu[1] = 1, is[1] = 1;
for(int i = 2 ; i <= N ; ++i){
if(!is[i]){
prime[++cnt] = i;
mu[i] = -1;
}
for(int j = 1 ; j <= cnt && i * prime[j] <= N ; ++j){
is[i * prime[j]] = 1;
if(i % prime[j] == 0){
mu[i * prime[j]] = 0;
break;
} else{
mu[i * prime[j]] = -mu[i];
}
}
}
for(int i = 1 ; i <= N ; ++i){
v.clear();
ll s1 = 0, s2 = 0, s3 = 0, s = 0;
ll K = 0;
for(int j = i ; j <= N ; j += i){ // 统计集合大小
if(!c[j]) continue;
K += c[j];
s = (s + 1ll * j * c[j] % M) % M;
v.emplace_back(j, c[j]);
}
for(auto j : v){
ll tt = 0;
if(K >= 2){
tt = qsm(2, K - 2);
s1 = (s1 + 1ll * j.first * j.first % M * ((K - 1) % M) % M * tt % M * j.second % M) % M;
}
if(K >= 3){
tt = (tt + 1LL * (K - 2) % M * tt % M * inv % M) % M;
}
s2 = (s2 + 1LL * j.first * j.first % M * tt % M * j.second % M * (j.second - 1) % M) % M;
s3 = (s3 + 1LL * j.first * j.second % M * tt % M * (s - 1LL * j.first * j.second % M) % M) % M;
}
ans = ((ans + 1ll * mu[i] * ((s1 + s2 + s3) % M)) % M + M) % M;
}
printf("%lld
", ans);
return 0;
}