求 HACK 做法
查看原帖
求 HACK 做法
397329
To_our_starry_sea楼主2024/8/24 22:38

rt。本题我的思路是首先分解出所有小于 1010310^{\frac{10}{3}} 的质因数,并取出质因数中所有指数模 33 不为 00 的数以及其指数对 33 取模的结果,再判断剩下的值 ss 是否为质数,或者为完全平方数,若是则将其所有质因数及其的指数哈希,并同时求出与其相乘为完全立方数的数的哈希结果,然而 WA 和 AC 数量几乎相等。请问这么做的正确概率是错误的吗,还是我的实现有问题。

代码如下:

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define ull unsigned long long
const int MAXN = 100005;
const ull base = 131;
ll n, cnt = 0, ans = 0, prime[MAXN], sta[15], pd[MAXN]; 
ll maxn = 0, a[MAXN];
ull HASH[MAXN][2], num[15] = {8, 3, 2, 4, 5, 7, 9, 1, 6};
bool vis[MAXN];
mt19937 RAND(time(0));
map<ull, int> mp, bel;
inline ll qmi(ll a, ll b, ll MOD) {
	ll res = a % MOD, ans = 1;
	while (b) {
		if (b & 1) ans = ans * res % MOD;
		res = res * res % MOD;
		b >>= 1;
	}
	return ans;
}
inline bool millerRabin(ll n) {
    if (n < 3 || n % 2 == 0) return (n == 2);
    ll a = n - 1 , b = 0 , T = 11;
    while (a % 2 == 0) a >>= 1, b++;
    for (int i = 1; i <= T; i++) {
        ll x = 1ll * RAND() * RAND() % (n - 2) + 2 , v = qmi(x, a, n);
        if (v == 1) continue;
		int j;
        for(j = 1; j <= b; j++) {
            if (v == n - 1) break;
            v = (ll)v * v % n;
        }
        if (j > b) return false;
    }
    return true;
}
inline void euler(int maxn) {
	for (int i = 2; i <= maxn; i++) {
    	if (!vis[i]) prime[++cnt] = i;
    	for (int j = 1; j <= cnt && prime[j] <= maxn / i; j++) {
    		vis[i * prime[j]] = 1;
    		if (i % prime[j] == 0) break;
		}
	}
}
inline int read() {
	int x = 0, f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
		   f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}
inline ll Read() {
	ll x = 0, f = 1; char ch = getchar();
	while (ch < '0' || ch > '9') {
		if (ch == '-')
		   f = -1;
		ch = getchar();
	}
	while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();
	return x * f;
}
int main() {
	srand(time(0));
	n = read();
	for (int i = 1; i <= n; i++) a[i] = Read(), maxn = max(maxn, a[i]);
	ll now = 2500;
	euler(now);
	for (int i = 1; i <= n; i++) {
		now = a[i];
		for (int j = 1; j <= cnt; j++) {
			int res = 0;
			while (now % prime[j] == 0) res++, now /= prime[j];
			res %= 3;
			if (!res) continue;
			int pos = 0, X = prime[j];
			while (X) sta[++pos] = X % 10, X /= 10;
			for (int k = 1; k <= pos; k++) HASH[i][0] = HASH[i][0] * base + num[sta[k]], HASH[i][1] = HASH[i][1] * base + num[sta[k]];
			HASH[i][0] = HASH[i][0] * base + (ull)res;
			HASH[i][1] = HASH[i][1] * base + (ull)(3 - res);
	        HASH[i][0] = HASH[i][0] * base + 10;
	        HASH[i][1] = HASH[i][1] * base + 10;
		}
		if (now == 1) continue;
		if (millerRabin(now)) {
			int pos = 0, X = now;
			while (X) sta[++pos] = X % 10, X /= 10;
			for (int k = 1; k <= pos; k++) HASH[i][0] = HASH[i][0] * base + num[sta[k]], HASH[i][1] = HASH[i][1] * base + num[sta[k]];
			HASH[i][0] = HASH[i][0] * base + 1;
			HASH[i][1] = HASH[i][1] * base + 2;
			HASH[i][0] = HASH[i][0] * base + 10;
	        HASH[i][1] = HASH[i][1] * base + 10;
	        continue;
		}
		ll l = 1, r = now, way = 1;
		while (l <= r) {
			ll mid = (l + r) >> 1;
			if (mid * mid <= now) way = max(way, mid), l = mid + 1;
			else r = mid - 1; 
		}
		if (way * way == now && millerRabin(way)) {
			int pos = 0, X = way;
			while (X) sta[++pos] = X % 10, X /= 10;
			for (int k = 1; k <= pos; k++) HASH[i][0] = HASH[i][0] * base + num[sta[k]], HASH[i][1] = HASH[i][1] * base + num[sta[k]];
			HASH[i][0] = HASH[i][0] * base + 2;
			HASH[i][1] = HASH[i][1] * base + 1;
			HASH[i][0] = HASH[i][0] * base + 10;
	        HASH[i][1] = HASH[i][1] * base + 10;
	        continue;
		}
		pd[i] = -1;
	} 
	for (int i = 1; i <= n; i++) {
		if (pd[i] == -1) continue;
		if (bel[HASH[i][0]] == 0) bel[HASH[i][0]] = i;
		mp[HASH[i][0]]++;
 	}
 	for (int i = 1; i <= n; i++) {
 		if (pd[i] == -1 || bel[HASH[i][0]] != i) continue;
 		if (HASH[i][0] == 0) {
 			ans++;
 			continue;
		 }
 		if (mp.find(HASH[i][1]) != mp.end()) {
 			ans += max(mp[HASH[i][0]], mp[HASH[i][1]]);
 			bel[HASH[i][0]] = bel[HASH[i][1]] = 0;
		}
		else ans += mp[HASH[i][0]];
	}
	printf("%lld\n", ans);
	return 0;
}
2024/8/24 22:38
加载中...