Namomo Camp Div1 合适数对(数据加强版)
作者:互联网
合适数对(数据加强版)
思路:
我们考虑一个数什么时候可以表示为\(x ^ {k}\),先把\(x\)进行质因数分解可以得到\(x = p_{1}^{t_1} * p_{2} ^ {t_2} \dots * p_{n} ^ {t_n}\),所以\(x ^ {k}\)就可以表示为\(x ^ {k} = p_{1} ^ {k_1} * p_{2} ^ {k_2} \dots * p_{n} ^ {k_n}\), 其中\(k_1, k_2, k_3 \dots k_t\) 都是\(k\)的倍数
所以我们在考虑\(p*q=x^{k}\)的时候,只需要保证\(p * q\)分解质因数的结果中每一个因数的指数都可以被\(k\)整除。那么我们对序列中每一个数进行质因数分解的时候,对于每一个质因数的幂次都\(\%k\)并将结果存在\(p\)中,即\(p = p_{1} ^ {k_1} * p_{2} ^ {k_2} \dots * p_{n} ^ {k_n}\), 在我们得到\(p\)之后,我们只需要判断我们可以求得有多少个匹配的\(q\)并更新答案。
由于数据量达到了\(10 ^ {7}\),如果用\(O(\sqrt{n})\)的朴素判素数明显是不行的,所以我们应该用欧拉筛\(O(n)\)来求的所有数的最小质因子。当然我们在筛素数的时候很明显所有的偶数都是一定会被\(2\)给筛掉的,所以我们在筛素数的时候可以直接将所有的偶数跳过,不对它们筛素数,这样可以优化一下筛法的常数。
void Eular(int n) {
prime[idx ++ ] = 2;
minp[2] = 2;
st[2] = true;
for (int i = 3; i <= n; i += 2) {
if (!st[i]) prime[idx ++ ] = i, minp[i] = i, st[i] = true;
for (int j = 0; prime[j] * i <= n; j ++ ) {
st[prime[j] * i] = true;
minp[prime[j] * i] = prime[j];
if (i % prime[j] == 0) break;
}
}
}
\(code\)
int n, k;
n = read(), k = read();
std::vector<int> a(n);
for (auto &I : a) I = read();
int mx = *max_element(a.begin(), a.end());
Eular(mx);
std::vector<i64> mp(mx + 1);
i64 ans = 0;
for (int i = 0; i < n; i ++ ) {
i64 p = 1, q = 1;
while (a[i] > 1) {
int val = (a[i] & 1) ? minp[a[i]] : 2;
int cnt = 0;
while (a[i] % val == 0) {
cnt ++ ;
a[i] /= val;
}
while (cnt >= k) cnt -= k;
p *= qmi(val, cnt);
if (cnt) q *= qmi(val, k - cnt);
if (q < 0 || q > mx) q = 0;
}
ans += mp[q];
mp[p] ++;
}
printf("%lld\n", ans);
标签:dots,cnt,数对,加强版,val,int,Camp,++,mx 来源: https://www.cnblogs.com/Haven-/p/16142874.html