CF1016G. Appropriate Team
Solution
相当于选出的两个数需要满足不存在一个质因子 p p p, a i a_i ai在 p p p的指数比 X X X多, a j a_j aj在 p p p的指数比 Y Y Y少。
我们用 P o l l a r d − p h o Pollard-pho Pollard−pho求出 Y Y Y所有最多 15 15 15个质因数,然后把所有能整除 Y Y Y的数表示为一个二进制数,表示该位上的指数相对于 X X X是否增加,存到桶里,记为 F F F;同样地再把相对 Y Y Y减的处理后的桶记作 G G G。
答案即为 [ x 0 ] ( F & G ) [x^0](F\&G) [x0](F&G),其中 & \& &表示 a n d and and卷积, F W T FWT FWT即可。
Code
#include <bits/stdc++.h>
using namespace std;
template<typename T> inline bool upmin(T &x, T y) { return y <= x ? x = y, 1 : 0; }
template<typename T> inline bool upmax(T &x, T y) { return x <= y ? x = y, 1 : 0; }
#define MP(A,B) make_pair(A,B)
#define PB(A) push_back(A)
#define SIZE(A) ((int)A.size())
#define LEN(A) ((int)A.length())
#define FOR(i,a,b) for(int i=(a);i<(b);++i)
#define fi first
#define se second
typedef long long ll;
typedef unsigned long long ull;
typedef long double lod;
typedef pair<int, int> PR;
typedef vector<int> VI;
const lod eps = 1e-9;
const lod pi = acos(-1);
const int oo = 1 << 30;
const ll loo = (1ll << 62) - 1;
const int MAXN = 1000005;
const int INF = 0x3f3f3f3f; //1061109567
/*--------------------------------------------------------------------*/
namespace FastIO{
constexpr int SIZE = (1 << 21) + 1;
int num = 0, f;
char ibuf[SIZE], obuf[SIZE], que[65], *iS, *iT, *oS = obuf, *oT = obuf + SIZE - 1, c;
#define gc() (iS == iT ? (iT = ((iS = ibuf) + fread(ibuf, 1, SIZE, stdin)), (iS == iT ? EOF : *iS ++)) : *iS ++)
inline void flush() {
fwrite(obuf, 1, oS - obuf, stdout);
oS = obuf;
}
inline void putc(char c) {
*oS ++ = c;
if (oS == oT) flush();
}
inline void getc(char &c) {
for (c = gc(); !isalpha(c) && c != EOF; c = gc());
}
inline void reads(char *st) {
char c;
int n = 0;
getc(st[++ n]);
for (c = gc(); isalpha(c) ; c = gc()) st[++ n] = c;
st[++ n] = '\0';
}
template<class I>
inline void read(I &x) {
for (f = 1, c = gc(); c < '0' || c > '9' ; c = gc()) if (c == '-') f = -1;
for (x = 0; c >= '0' && c <= '9' ; c = gc()) x = (x << 3) + (x << 1) + (c & 15);
x *= f;
}
template<class I>
inline void print(I x) {
if (x < 0) putc('-'), x = -x;
if (!x) putc('0');
while (x) que[++ num] = x % 10 + 48, x /= 10;
while (num) putc(que[num --]);
}
inline void putstr(string st) {
for (int i = 0; i < (int)st.size() ; ++ i) putc(st[i]);
}
struct Flusher_{~Flusher_(){flush();}} io_Flusher_;
}
using FastIO :: read;
using FastIO :: putc;
using FastIO :: putstr;
using FastIO :: reads;
using FastIO :: print;
int a[20], b[20];
ll c[MAXN], f[MAXN], g[MAXN], P[20];
namespace Number_Theoretic{
const int MX = 1e6;
map<ll, int> Map;
int test[8] = {2, 3, 5, 7, 11, 13, 82, 373};
int flag[MAXN], prime[MAXN], mn[MAXN], pnum = 0;
ll Mul(ll x, ll y, ll mods) { return (__int128)x * y % mods; }
ll quick_pow(ll x, ll y, ll mods) {
ll ret = 1;
for (; y ; y >>= 1) {
if (y & 1) ret = Mul(ret, x, mods);
x = Mul(x, x, mods);
}
return ret;
}
void Init(int n) {
for (int i = 2; i <= n ; ++ i) {
if (!flag[i]) prime[++ pnum] = i, mn[i] = pnum;
for (int j = 1; j <= pnum && prime[j] * i <= n ; ++ j) {
flag[prime[j] * i] = 1, mn[prime[j] * i] = j;
if (!(i % prime[j])) break;
}
}
}
int Miller_Rabin(ll n) {
if (n <= MX) return (n > 1) && (prime[mn[n]] == n);
int c = 0; ll s = n - 1, u, v;
for (; !(s & 1) ;) s >>= 1, ++ c;
for (int i = 0; i < 8 ; ++ i) {
if (!(n % test[i])) return 0;
u = quick_pow(test[i], s, n);
for (int j = 0; j < c ; ++ j, u = v)
if (v = Mul(u, u, n), u != 1 && u != n - 1 && v == 1) return 0;
if (u != 1) return 0;
}
return 1;
}
ll Pollard_Rho(ll n, int c) {
ll x = rand() % (n - 1) + 1, y = x, tmp = 1;
for (int k = 2, nw = 1; k <= 131072 ; ) {
x = (Mul(x, x, n) + c) % n;
tmp = Mul(tmp, (y - x + n) % n, n);
if (nw % 128 == 0 || nw + 1 == k) {
ll t = __gcd(tmp, n);
if (t != 1 && t != n) return t;
tmp = 1;
}
if ((++ nw) == k) y = x, k <<= 1;
}
return 0;
}
void Push(ll x, int y) { Map[x] += y; }
void Factor(ll n) {
while (n > 1) {
if (n <= MX) {
int num = 0, p = prime[mn[n]];
while (n % p == 0) n /= p, ++ num;
Push(p, num);
}
else {
ll p;
if (Miller_Rabin(n)) { Push(n, 1); break; }
for (int k = 97; !(p = Pollard_Rho(n, k)) ; -- k);
n /= p, Factor(p);
}
}
}
}
using namespace Number_Theoretic;
void Fwt(ll *A, int n, int opt) {
for (int i = 0; i < n ; ++ i)
for (int j = 0; j < 1 << n ; ++ j)
if (!((j >> i) & 1)) A[j] += A[j ^ (1 << i)] * opt;
}
signed main() {
#ifndef ONLINE_JUDGE
freopen("a.in", "r", stdin);
#endif
Init(MX);
int n, num = 0; ll X, Y, t;
read(n), read(X), read(Y), t = X;
for (int i = 1; i <= n ; ++ i) read(c[i]);
if (Y % X) { print(0); return 0; }
Factor(Y);
for (auto v : Map) ++ num, P[num] = v.fi, b[num] = v.se;
for (int j = 1; j <= num ; ++ j)
while (t % P[j] == 0) t /= P[j], ++ a[j];
for (int i = 1; i <= n ; ++ i) {
int fa = 0, fb = 0; ll p = c[i];
for (int j = 1; j <= num ; ++ j) {
if (a[j] == b[j]) continue;
int t = 0;
while (p % P[j] == 0) p /= P[j], ++ t;
// cout << c[i] << " " << P[j] << " " << t << " " << a[j] << endl;
if (t != a[j]) fa |= (1 << (j - 1));
if (t != b[j]) fb |= (1 << (j - 1));
}
if (!(c[i] % X)) ++ f[fa];
if (!(Y % c[i])) ++ g[fb];
}
Fwt(f, num, 1);
Fwt(g, num, 1);
for (int i = 0; i < 1 << num ; ++ i) f[i] = f[i] * g[i];
Fwt(f, num, -1);
print(f[0]);
return 0;
}