F. Sum Over Subsets
题意:
给定一个集合S,求所有A,B集合,满足以下条件:
1.B⊂AB \subset AB⊂A
2.∣B∣=∣A∣−1|B|=|A|-1∣B∣=∣A∣−1
3.gcd(A)=1gcd(A)=1gcd(A)=1
对所有的A,B集合求和∑x∈Ax⋅∑x∈Bx\sum_{x\in A}x \cdot \sum_{x\in B}x∑x∈Ax⋅∑x∈Bx
结果对998244353998244353998244353取余
题解:
忽略条件3,计算此时的和,假设∣S∣=k|S|=k∣S∣=k。
- ai⋅aia_i \cdot a_iai⋅ai被计算2k−2(k−1)2^{k-2}(k-1)2k−2(k−1)次,其中k−1k-1k−1表示AAA比BBB多的那个元素方案,2k−22^{k-2}2k−2表示剩下元素的方案。
- ai⋅aja_i \cdot a_jai⋅aj被计算2k−3(k−2)+2k−22^{k-3}(k-2)+2^{k-2}2k−3(k−2)+2k−2次,前半部分表示ai∈Aa_i \in Aai∈A且ai∈Ba_i \in Bai∈B时的方案数,后半部分表示ai∈Aa_i \in Aai∈A ai∉Ba_i \notin Bai∈/B的方案。
条件3可以利用容斥的思想。设f[i]f[i]f[i]表示gcd(S)=igcd(S)=igcd(S)=i的答案,g[i]g[i]g[i]表示i∣gcd(S)i|gcd(S)i∣gcd(S)的答案。现在是已知ggg求fff。
那么f[i]=g[i]−∑i∣j,i!=jf[j]f[i]=g[i]-\sum_{i|j,i!=j}f[j]f[i]=g[i]−∑i∣j,i!=jf[j]。
#include<bits/stdc++.h>
using namespace std;
#define LL long long
const int mod = 998244353;
const int N = 1e5 + 5;
int a[N], freq[N], sum[N], sumsquare[N], f[N], g[N];
LL num[N];
int qpow(int x, LL y) {
int ans = 1;
while (y) {
if (y & 1) {
ans = 1ll * ans * x % mod;
}
x = 1ll * x * x % mod;
y /= 2;
}
return ans;
}
int main() {
int m;
scanf("%d", &m);
for (int i = 1; i <= m; i++) {
scanf("%d %d", &a[i], &freq[i]);
num[a[i]] = num[a[i]] + freq[i];
sum[a[i]] = (sum[a[i]] + 1ll * a[i] * freq[i] % mod) % mod;
sumsquare[a[i]] = (sumsquare[a[i]] + 1ll * a[i] * a[i] % mod * freq[i] % mod) % mod;
}
for (int i = 1; i < N; i++) {
for (int j = 2 * i; j < N; j += i) {
num[i] = num[i] + num[j];
sum[i] = (sum[i] + sum[j]) % mod;
sumsquare[i] = (sumsquare[i] + sumsquare[j]) % mod;
}
}
for (int i = 1; i < N; i++) {
LL k = num[i];
if (k >= 2) {
g[i] = (g[i] + 1ll * sumsquare[i] * qpow(2, k - 2) % mod * ((k - 1) % mod) % mod) % mod;
int temp = 0;
temp = (temp + 1ll * qpow(2, k - 3) * ((k - 2) % mod) % mod) % mod;
temp = (temp + 1ll * qpow(2, k - 2) % mod) % mod;
g[i] = (g[i] + 1ll * (1ll * sum[i] * sum[i] % mod - sumsquare[i] + mod) % mod * temp % mod) % mod;
}
}
for (int i = N - 1; i >= 1; i--) {
f[i] = g[i];
for (int j = 2 * i; j < N; j += i) {
f[i] = (f[i] - f[j] + mod) % mod;
}
}
printf("%d\n", f[1]);
return 0;
}