其实有一个很有用的技巧就是,把gcd = 4的贡献,压去gcd = 2时的贡献,就不需要考虑这么多的了。
为什么可以把gcd = 4的,压去gcd = 2的呢,gcd = 12的,压去gcd = 6的去算呢,
其实这就是mobius的容斥原理,mu[4] = 0,mu[12] = 0,
例如:
http://www.cnblogs.com/liuweimingcprogram/p/6818754.html
这题的思路是,把每个数字都质因数分解,比如分解成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 - calc(val)); } } int main() { #ifdef local freopen("data.txt", "r", stdin); // freopen("data.txt", "w", stdout); #endif initPrime(); work(); return 0; }