CF1016G. Appropriate Team(Pollard-pho,FWT,数论)

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 Pollardpho求出 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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值