其实有一个很有用的技巧就是,把gcd = 4的贡献,压去gcd = 2时的贡献,就不需要考虑这么多的了。
为什么可以把gcd = 4的,压去gcd = 2的呢,gcd = 12的,压去gcd = 6的去算呢,
其实这就是mobius的容斥原理,mu[4] = 0,mu[12] = 0,
这题的思路是,把每个数字都质因数分解,比如分解成12 = 2 * 3
然后暴力枚举每个质因子选or不选,就能知道,12的所有因子,
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;
#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int maxn = 100000 + 20;
int prime[maxn][12];
void initPrime() {
int mx = 0;
for (int i = 2; i <= maxn - 20; ++i) {
if (prime[i][0]) continue;
for (int j = i; j <= maxn - 20; j += i) {
prime[j][++prime[j][0]] = i;
// mx = max(mx, prime[j][0]);
}
}
}
int num[maxn];
void init(int val) {
int en = (1 << prime[val][0]) - 1;
for (int i = 1; i <= en; ++i) {
int t = 1;
for (int j = 1; j <= prime[val][0]; ++j) {
if (i & (1 << (j - 1))) {
t *= prime[val][j];
}
}
num[t]++;
}
}
int calc(int val) {
int ans = 0;
int en = (1 << prime[val][0]) - 1;
for (int i = 1; i <= en; ++i) {
int t = 1;
int cnt = 0;
for (int j = 1; j <= prime[val][0]; ++j) {
if (i & (1 << (j - 1))) {
t *= prime[val][j];
cnt++;
}
}
if (cnt & 1) ans += num[t];
else ans -= num[t];
}
return ans;
}
void work() {
// int out = 3 * 5 * 7;
// for (int i = 1; i <= prime[out][0]; ++i) {
// printf("%d ", prime[out][i]);
// }
int n, q;
scanf("%d%d", &n, &q);
for (int i = 1; i <= n; ++i) {
int val;
scanf("%d", &val);
init(val);
}
for (int i = 1; i <= q; ++i) {
int val;
scanf("%d", &val);
printf("%d\n", n - calc(val));
}
}
int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
initPrime();
work();
return 0;
}
View Code
标签:prime,12,gcd,val,int,拒接,18087,include,scau From: https://blog.51cto.com/u_15833059/5779575