codeforces 803 F. Coprime Subsequences (莫比乌斯反演)

题目链接:https://codeforces.com/problemset/problem/803/F

按莫比乌斯函数系数容斥即可,统计 \(gcd\) 至少为 \(i\) 的子序列的数量,即 \(i\) 的倍数的数选或不选,方案数为 \(2^{size[i]}-1\)

统计序列中 \(i\) 的倍数的元素的个数,\(O(nlogn)\) 枚举倍数统计即可

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const int maxn = 100010;
const int M = 1000000007;

int n, cnt;
int a[maxn];
int prime[1000010], mu[1000010], is_prime[1000010];

vector<int> fac[1000010];

int qsm(int i, int po){
	int res = 1;
	while(po){
		if(po & 1) res = 1ll * res * i % M;
		i = 1ll * i * i % M;
		po >>= 1;
	}
	return res;
}

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(){
	mu[1] = 1;
	for(int i = 2; i <= 1000000; ++i){
		if(!is_prime[i]){
			prime[++cnt] = i;
			mu[i] = -1;
		}
		for(int j = 1 ; j <= cnt && prime[j] * i <= 1000000 ; ++j){
			is_prime[i * prime[j]] = 1;
			if(i % prime[j] == 0) {
				mu[i * prime[j]] = 0;
				break;
			} else {
				mu[i * prime[j]] = -mu[i];
			}
		}
	}
	
	n = read();
	int c1 = 0;
	for(int i = 1 ; i <= n ; ++i) {
		a[i] = read();
		if(a[i] == 1) ++c1;
	}
	
	for(int i = 1 ; i <= n ; ++i){
		for(int j = 1 ; j <= (int)sqrt(a[i]+0.5) ; ++j){
			if(a[i] % j == 0){
				fac[j].push_back(a[i]);
				if(j * j != a[i]) fac[a[i]/j].push_back(a[i]);
			}
		}
	}
	
	int ans = ((qsm(2, n) - 1) % M + M) % M;
	for(int i = 2 ; i <= 1000000 ; ++i){
		if(mu[i] != 0 && fac[i].size()){
			ans = ((ans + 1ll * mu[i] * (qsm(2, fac[i].size()) - 1) % M) % M + M) % M;
		}
	}
	printf("%d\n", ans);
	
	return 0;
}
posted @ 2021-09-08 17:21  Tartarus_li  阅读(46)  评论(0编辑  收藏  举报