CF585E

sn 表示最大公因数恰好为 n 的集合个数,fn 表示与 n 互质的数的个数。

那么我们要求的就是 isifi

考虑求出 sf

考虑计算 fi。令 ci 表示数 i 的出现次数。

则直接莫比乌斯反演:

fn=i[gcd(i,n)=1]ci

=icidi,dnμ(d)

=dnμ(d)dici

gk=kici,gk=μ(k)gk,那么 fn=dngd

发现这个 gi 就表示 i 的倍数的出现次数。

再考虑求 si。我们令 si 表示最大公因数为 i 的倍数的方案数。要使最大公因数为 i 的倍数,那么每个选的数必须是 i 的倍数。所以容易得到 si=2gi1

又有 si=idsd

观察上面的式子的形式,它们都是这样的形式:

bk=ikai

bk=kiai

其中,上面的式子为狄利克雷前缀和,下面的式子为狄利克雷后缀和

这都可以在 O(wloglogw) 的时间内求出,可以先去做一下【模板】Dirichlet 前缀和(这个实际上就是一个关于质因子分解后的指数的高维前缀和,使用类似 FMT 的方法就可以了)。

计算 gf 都是标准的狄利克雷前/后缀和形式。

但还有个问题,已知 ab 能做了,但是那个 s 的计算,是已知 ba 的。

前面是加,那现在就把它改成减就可以了。当然也可以用高维前缀和的知识解释。

总时间复杂度 O(n+wloglogw)

具体细节看代码。

Code:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 500005, M = 10000000, mod = 1e9 + 7;
int n, ans;
int a[N], cnt[M+5];
int mu[M+5];
int pri[M / 10], tot;
bool vis[M+5];
int pw[N];
int f[M], g[M];

inline void add(int &a, int b) {
	a += b;
	if (a >= mod) a -= mod;
	if (a < 0) a += mod;
}

void init(int n) {
	pw[0] = 1;
	for (int i = 1; i <= 500000; ++i) pw[i] = 1ll * pw[i - 1] * 2 % mod;
	mu[1] = 1;
	for (int i = 2; i <= n; ++i) {
		if (!vis[i]) pri[++tot] = i, mu[i] = -1;
		for (int j = 1; j <= tot && i * pri[j] <= n; ++j) {
			vis[i * pri[j]] = 1;
			if (i % pri[j] == 0) {
				mu[i * pri[j]] = 0;
				break;
			}
			mu[i * pri[j]] = -mu[i];
		}
	}
}

int main() {
	init(M);
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), ++cnt[a[i]];
	for (int i = 1; i <= tot; ++i)
		for (int j = M / pri[i]; j; --j)
			add(cnt[j], cnt[j * pri[i]]);
	for (int i = 1; i <= M; ++i) g[i] = cnt[i] * mu[i];
	for (int i = 1; i <= tot; ++i)
		for (int j = 1; j * pri[i] <= M; ++j)
			add(g[j * pri[i]], g[j]);
	for (int i = 1; i <= M; ++i) f[i] = pw[cnt[i]] - 1;
	for (int i = 1; i <= tot; ++i)
		for (int j = 1; j * pri[i] <= M; ++j)
			add(f[j], -f[j * pri[i]]);
	for (int i = 2; i <= M; ++i) add(ans, 1ll * f[i] * g[i] % mod);
	printf("%d", ans);
	return 0;
}
posted @   Kobe303  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示