(1)题目大意
给你一个字符串,问你让字符串每一对相对应位置都不同的最小操作数是多少?(A[i]和A[n - i],A[i + 1]和A[n - i - 1])
(2)解题思路
1.首先字符串为奇数一定不可以
2.其次如果字符串中某个字母的个数>n/2,则也不可以
3.答案的构成,不会证明。
考虑主元素法,答案要么就是最大的相同对的字母或者是总共的相同对的总数/2,这两个取个max就行了。
(3)代码实现
#include<bits/stdc++.h>
#define sz(x) (int) x.size()
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
using ll = long long;
const int N = 5e5 + 10;
void solve(){
int n;
cin >> n;
string s;
cin >> s;
vector <int> cnt(26);
if(n & 1) {
cout << -1 << endl;
return;
}
for(auto x : s) cnt[x - 'a'] ++;
int mx = 0;
for(int i = 0;i < 26;i ++) {
if(cnt[i] > n / 2) {
cout << -1 << endl;
return;
}
}
int l = 0,r = n - 1,ans = 0;
for(int i = 0;i < 26;i ++) cnt[i] = 0;
while(l < r) {
if(s[l] == s[r]) cnt[s[l] - 'a'] ++,ans ++;
l ++,r --;
}
for(int i = 0;i < 26;i ++) mx = max(mx,cnt[i]);
cout << max((ans + 1) / 2,mx) << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1;
cin >> T;
while(T --) solve();
}
(1)题目大意
(2)解题思路
考虑找到最长的那条链,做两次dfs即可,或者考虑换根dp,我的做法是两次dfs,首先从1跑一遍dfs记录一下深度,然后从最远的那个点再跑一次dfs即可。
记第一次dfs处理的数组为dp1,第二次的数组为dp2,则有两种情况
1.需要进行操作:ans = max(ans,dp2[i] * k - dp1[i] * c);
2.不需要进行操作: ans = max(ans,dp1[i]*k);
(3)代码实现
#include<bits/stdc++.h>
#define sz(x) (int) x.size()
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
using ll = long long;
const int N = 3e5 + 10;
vector <int> g[N];
int dp1[N],dp2[N];
void dfs1(int u,int f)
{
for(auto v : g[u]) {
if(v == f) continue;
dp1[v] = dp1[u] + 1;
dfs1(v,u);
}
}
void dfs2(int u,int f)
{
for(auto v : g[u]) {
if(v == f) continue;
dp2[v] = dp2[u] + 1;
dfs2(v,u);
}
}
void solve(){
int n,k,c;
cin >> n >> k >> c;
for(int i = 1;i <= n;i ++) g[i].clear();
for(int i = 1;i <= n - 1;i ++) {
int u,v;
cin >> u >> v;
g[u].pb(v),g[v].pb(u);
}
dp1[1] = 0;
dfs1(1,0);
int rt = 1;
for(int i = 1;i <= n;i ++) {
if(dp1[i] > dp1[rt])
rt = i;
}
dp2[rt] = 0;
dfs2(rt,0);
ll ans = 0;
for(int i = 1;i <= n;i ++) {
ans = max(ans,1ll * dp1[i] * k);
ans = max(ans,1ll * dp2[i] * k - 1ll * dp1[i] * c);
}
cout << ans << endl;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1;
cin >> T;
while(T --) solve();
}
(1)题目大意
给你一个长度为n的序列,让你找到i,j,k的对数,满足a[j] = b * a[i],a[k] = b * a[j]。
(2)解题思路
G1我们直接枚举暴力即可,但是G2发现a[i]有1e9,因此我们考虑使用PollardRho暴力分解质因子,然后根据质数平方因子处理出两个数组出来,再根据这些因子计算答案即可。
(3)代码实现
#include "bits/stdc++.h"
#include <cstdint>
#include <functional>
#include <random>
#include <cmath>
#include <cstdint>
#include <functional>
#include <memory>
#include <cassert>
#include <cstdint>
#include <functional>
#include <algorithm>
#include <cstdint>
#include <cassert>
#include <cstdint>
#include <initializer_list>
#define sz(x) (int) x.size()
#define rep(i,z,n) for(int i = z;i <= n; i++)
#define per(i,n,z) for(int i = n;i >= z; i--)
#define PII pair<int,int>
#define fi first
#define se second
#define vi vector<int>
#define vl vector<ll>
#define pb push_back
#define all(x) (x).begin(),(x).end()
using namespace std;
using ll = long long;
using pii = std::pair<int, int>;
using pll = std::pair<ll, ll>;
const int N = 1e6 + 10;
int a[N];
namespace OY {
template <typename _ModType>
struct Barrett {
_ModType m_P;
__uint128_t m_Pinv;
constexpr Barrett() = default;
constexpr explicit Barrett(_ModType __P) : m_P(__P), m_Pinv(-uint64_t(__P) / __P + 1) {}
constexpr _ModType mod() const { return m_P; }
constexpr _ModType mod(uint64_t __a) const {
__a -= uint64_t(m_Pinv * __a >> 64) * m_P + m_P;
if (__a >= m_P) __a += m_P;
return __a;
}
constexpr _ModType multiply(uint64_t __a, uint64_t __b) const {
if constexpr (std::is_same_v<_ModType, uint64_t>)
return multiply_ld(__a, __b);
else
return multiply_64(__a, __b);
}
constexpr _ModType multiply_64(uint64_t __a, uint64_t __b) const {
// assert(__a * __b < 1ull << 64);
return mod(__a * __b);
}
constexpr _ModType multiply_128(uint64_t __a, uint64_t __b) const {
if (__builtin_clzll(__a) + __builtin_clzll(__b) >= 64) return multiply_64(__a, __b);
return __uint128_t(__a) * __b % m_P;
}
constexpr _ModType multiply_ld(uint64_t __a, uint64_t __b) const {
// assert(m_P < 1ull << 63 && __a < m_P && __b < m_P);
if (__builtin_clzll(__a) + __builtin_clzll(__b) >= 64) return multiply_64(__a, __b);
int64_t res = __a * __b - uint64_t(1.L / m_P * __a * __b) * m_P;
if (res < 0)
res += m_P;
else if (res >= m_P)
res -= m_P;
return res;
}
constexpr _ModType pow(uint64_t __a, uint64_t __n) const {
if constexpr (std::is_same_v<_ModType, uint64_t>)
return pow_ld(__a, __n);
else
return pow_64(__a, __n);
}
constexpr _ModType pow_64(uint64_t __a, uint64_t __n) const {
// assert(m_P < 1ull << 32);
_ModType res = 1, b = mod(__a);
while (__n) {
if (__n & 1) res = multiply_64(res, b);
b = multiply_64(b, b);
__n >>= 1;
}
return res;
}
constexpr _ModType pow_128(uint64_t __a, uint64_t __n) const {
_ModType res = 1, b = mod(__a);
while (__n) {
if (__n & 1) res = multiply_128(res, b);
b = multiply_128(b, b);
__n >>= 1;
}
return res;
}
constexpr _ModType pow_ld(uint64_t __a, uint64_t __n) const {
_ModType res = 1, b = mod(__a);
while (__n) {
if (__n & 1) res = multiply_ld(res, b);
b = multiply_ld(b, b);
__n >>= 1;
}
return res;
}
template <typename _Tp>
constexpr _Tp divide(_Tp __a) const {
if (__a < m_P) return 0;
_Tp res = m_Pinv * __a >> 64;
if (__a - res * m_P >= m_P) res++;
return res;
}
template <typename _Tp>
constexpr std::pair<_Tp, _Tp> divmod(_Tp __a) const {
_Tp quo = (__a * m_Pinv) >> 64, rem = __a - quo * m_P;
if (rem >= m_P) {
quo++;
rem -= m_P;
}
return {quo, rem};
}
};
using Barrett32 = Barrett<uint32_t>;
using Barrett64 = Barrett<uint64_t>;
}
namespace OY {
template <typename _ModType>
struct _MontgomeryTag;
template <>
struct _MontgomeryTag<uint32_t> {
using long_type = uint64_t;
static constexpr uint32_t limit = (1u << 30) - 1;
static constexpr uint32_t inv_loop = 4;
static constexpr uint32_t length = 32;
};
template <>
struct _MontgomeryTag<uint64_t> {
using long_type = __uint128_t;
static constexpr uint64_t limit = (1ull << 63) - 1;
static constexpr uint32_t inv_loop = 5;
static constexpr uint32_t length = 64;
};
template <typename _ModType>
struct Montgomery {
using _FastType = _ModType;
using _LongType = typename _MontgomeryTag<_ModType>::long_type;
_ModType m_P;
_ModType m_Pinv;
_ModType m_Ninv;
Barrett<_ModType> m_brt;
constexpr Montgomery() = default;
constexpr explicit Montgomery(_ModType __P) : m_P(__P), m_Pinv(__P), m_Ninv(-_LongType(__P) % __P), m_brt(__P) {
// assert((__P & 1) && __P > 1 && __P <= _MontgomeryTag<_ModType>::limit);
for (int i = 0; i < _MontgomeryTag<_ModType>::inv_loop; i++) m_Pinv *= _ModType(2) - __P * m_Pinv;
}
constexpr _ModType mod() const { return m_brt.mod(); }
constexpr _ModType mod(uint64_t __a) const { return m_brt.mod(__a); }
constexpr _FastType init(uint64_t __a) const { return reduce(_LongType(mod(__a)) * m_Ninv); }
constexpr _FastType raw_init(uint64_t __a) const { return reduce(_LongType(__a) * m_Ninv); }
constexpr _FastType reduce(_LongType __a) const {
_FastType res = (__a >> _MontgomeryTag<_ModType>::length) - _ModType(_LongType(_ModType(__a) * m_Pinv) * m_P >> _MontgomeryTag<_ModType>::length);
if (res >= mod()) res += mod();
return res;
}
constexpr _ModType reduce(_FastType __a) const {
_ModType res = -_ModType(_LongType(__a * m_Pinv) * m_P >> _MontgomeryTag<_ModType>::length);
if (res >= mod()) res += mod();
return res;
}
constexpr _FastType multiply(_FastType __a, _FastType __b) const { return reduce(_LongType(__a) * __b); }
constexpr _FastType pow(_FastType __a, uint64_t __n) const {
_FastType res = reduce(_LongType(1) * m_Ninv);
while (__n) {
if (__n & 1) res = multiply(res, __a);
__a = multiply(__a, __a);
__n >>= 1;
}
return res;
}
template <typename _Tp>
constexpr _Tp divide(_Tp __a) const { return m_brt.divide(__a); }
template <typename _Tp>
constexpr std::pair<_Tp, _Tp> divmod(_Tp __a) const { return m_brt.divmod(__a); }
};
using Montgomery32 = Montgomery<uint32_t>;
using Montgomery64 = Montgomery<uint64_t>;
}
namespace OY {
template <typename _Elem>
constexpr bool isPrime(_Elem n) {
if (std::is_same_v<_Elem, uint32_t> || n <= UINT32_MAX) {
if (n <= 1) return false;
if (n == 2 || n == 7 || n == 61) return true;
if (n % 2 == 0) return false;
Barrett32 brt(n);
uint32_t d = (n - 1) >> __builtin_ctz(n - 1);
for (auto &&a : {2, 7, 61}) {
uint32_t s = d, y = brt.pow_64(a, s);
while (s != n - 1 && y != 1 && y != n - 1) {
y = brt.multiply_64(y, y);
s <<= 1;
}
if (y != n - 1 && s % 2 == 0) return false;
}
return true;
} else {
// assert(n < 1ull < 63);
if (n % 2 == 0) return false;
Montgomery64 mg(n);
uint64_t d = (n - 1) >> __builtin_ctzll(n - 1), one = mg.init(1);
for (auto &&a : {2, 325, 9375, 28178, 450775, 9780504, 1795265022}) {
uint64_t s = d, y = mg.pow(mg.init(a), s), t = mg.init(n - 1);
while (s != n - 1 && y != one && y != t) {
y = mg.multiply(y, y);
s <<= 1;
}
if (y != t && s % 2 == 0) return false;
}
return true;
}
}
constexpr auto isPrime32 = isPrime<uint32_t>;
constexpr auto isPrime64 = isPrime<uint64_t>;
}
namespace OY {
template <typename _Elem>
constexpr _Elem gcd(_Elem a, _Elem b) {
if (!a || !b) return a | b;
int i = std::__countr_zero(a), j = std::__countr_zero(b), k = std::min(i, j);
a >>= i;
b >>= j;
while (true) {
if (a < b) std::swap(a, b);
if (!(a -= b)) break;
a >>= std::__countr_zero(a);
}
return b << k;
}
template <typename _Elem>
constexpr _Elem lcm(_Elem a, _Elem b) { return a && b ? a / gcd<_Elem>(a, b) * b : 0; }
constexpr auto gcd32 = gcd<uint32_t>;
constexpr auto gcd64 = gcd<uint64_t>;
constexpr auto lcm32 = lcm<uint32_t>;
constexpr auto lcm64 = lcm<uint64_t>;
}
namespace OY {
struct Pollard_Rho {
static constexpr uint64_t batch = 128;
static inline std::mt19937_64 s_rander;
template <typename _Elem>
static _Elem pick(_Elem __n) {
// assert(!isPrime<_Elem>(__n));
if (__n % 2 == 0) return 2;
static Montgomery<_Elem> mg;
if (mg.mod() != __n) mg = Montgomery<_Elem>(__n);
std::uniform_int_distribution<_Elem> distribute(2, __n - 1);
_Elem v0, v1 = mg.init(distribute(s_rander)), prod = mg.init(1), c = mg.init(distribute(s_rander));
for (int i = 1; i < batch; i <<= 1) {
v0 = v1;
for (int j = 0; j < i; j++) v1 = mg.multiply(v1, v1) + c;
for (int j = 0; j < i; j++) {
v1 = mg.multiply(v1, v1) + c;
prod = mg.multiply(prod, v0 > v1 ? v0 - v1 : v1 - v0);
if (!prod) return pick(__n);
}
if (_Elem g = gcd<_Elem>(prod, __n); g > 1) return g;
}
for (int i = batch;; i <<= 1) {
v0 = v1;
for (int j = 0; j < i; j++) v1 = mg.multiply(v1, v1) + c;
for (int j = 0; j < i; j += batch) {
for (int k = 0; k < batch; k++) {
v1 = mg.multiply(v1, v1) + c;
prod = mg.multiply(prod, v0 > v1 ? v0 - v1 : v1 - v0);
if (!prod) return pick(__n);
}
if (_Elem g = gcd<_Elem>(prod, __n); g > 1) return g;
}
}
return __n;
}
template <typename _Elem>
static auto decomposite(_Elem __n) {
struct node {
_Elem prime;
uint32_t count;
};
std::vector<node> res;
auto dfs = [&](auto self, _Elem cur) -> void {
if (!OY::isPrime<_Elem>(cur)) {
_Elem a = pick<_Elem>(cur);
self(self, a);
self(self, cur / a);
} else {
auto find = std::find_if(res.begin(), res.end(), [cur](auto x) { return x.prime == cur; });
if (find == res.end())
res.push_back({cur, 1u});
else
find->count++;
}
};
if (__n % 2 == 0) {
res.push_back({2, uint32_t(std::__countr_zero(__n))});
__n >>= std::__countr_zero(__n);
}
if (__n > 1) dfs(dfs, __n);
std::sort(res.begin(), res.end(), [](auto &x, auto &y) { return x.prime < y.prime; });
return res;
}
template <typename _Elem>
static std::vector<_Elem> getFactors(_Elem __n) {
auto pf = decomposite(__n);
std::vector<_Elem> res;
_Elem count = 1;
for (auto [p, c] : pf) count *= c + 1;
res.reserve(count);
auto dfs = [&](auto self, int i, _Elem prod) -> void {
if (i == pf.size())
res.push_back(prod);
else {
auto [p, c] = pf[i];
self(self, i + 1, prod);
while (c--) self(self, i + 1, prod *= p);
}
};
dfs(dfs, 0, 1);
std::sort(res.begin(), res.end());
return res;
}
template <typename _Elem>
static _Elem EulerPhi(_Elem __n) {
for (auto [p, c] : decomposite(__n)) __n = __n / p * (p - 1);
return __n;
}
};
}
void solve(){
int n;
cin >> n;
map <ll,int> cnt1,cnt2;
rep(i,1,n) {
cin >> a[i];
cnt1[a[i]] ++;
}
ll ans = 0;
for(auto [x,c] : cnt1) {
auto fac = OY::Pollard_Rho::decomposite<uint32_t>(x);
vector <int> v1,v2;
v1.pb(1),v2.pb(1);
if(c >= 3) ans += 1ll * c * (c - 1) * (c - 2);
for(auto [y,cc] : fac) {
for(int i = 1;i + 1 <= cc;i += 2) {
int ssz = sz(v1);
for(int j = 0;j < ssz;j ++) {
v1.pb(v1[j] * y);
v2.pb(v2[j] * y * y);
}
}
}
sort(all(v1));
sort(all(v2));
v1.erase(unique(all(v1)),v1.end());
v2.erase(unique(all(v2)),v2.end());
for(int i = 0;i < sz(v1);i ++) {
if(v1[i] == 1 || v2[i] == 1) continue;
if(cnt2.count(x / v1[i]) && cnt2.count(x / v2[i])) {
ans += 1ll * c * cnt2[x / v1[i]] * cnt2[x / v2[i]];
}
}
cnt2[x] = c;
}
cout << ans << '\n';
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
int T = 1;
cin >> T;
while(T --) solve();
}