Codeforces Round 867 (Div. 3) (E-G)

Problem - E - Codeforces

        (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();
}

Problem - F - Codeforces

        (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();
}

Problem - G2 - Codeforces

        (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();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值