Codeforces Round #614 (Div. 1) D. Chaotic V.

"Everything has been planned out. No more hidden concerns. The condition of Cytus is also perfect.

The time right now… 00:01:12…

It’s time."

The emotion samples are now sufficient. After almost 3 years, it’s time for Ivy to awake her bonded sister, Vanessa.

The system inside A.R.C.'s Library core can be considered as an undirected graph with infinite number of processing nodes, numbered with all positive integers (1,2,3,…). The node with a number 𝑥 (𝑥>1), is directly connected with a node with number 𝑥𝑓(𝑥), with 𝑓(𝑥) being the lowest prime divisor of 𝑥.

Vanessa’s mind is divided into 𝑛 fragments. Due to more than 500 years of coma, the fragments have been scattered: the 𝑖-th fragment is now located at the node with a number 𝑘𝑖! (a factorial of 𝑘𝑖).

To maximize the chance of successful awakening, Ivy decides to place the samples in a node 𝑃, so that the total length of paths from each fragment to 𝑃 is smallest possible. If there are multiple fragments located at the same node, the path from that node to 𝑃 needs to be counted multiple times.

In the world of zeros and ones, such a requirement is very simple for Ivy. Not longer than a second later, she has already figured out such a node.

But for a mere human like you, is this still possible?

For simplicity, please answer the minimal sum of paths’ lengths from every fragment to the emotion samples’ assembly node 𝑃.

Input

The first line contains an integer 𝑛 (1≤𝑛≤10^6) — number of fragments of Vanessa’s mind.

The second line contains 𝑛 integers: 𝑘1,𝑘2,…,𝑘𝑛 (0≤𝑘𝑖≤5000), denoting the nodes where fragments of Vanessa’s mind are located: the 𝑖-th fragment is at the node with a number 𝑘𝑖!.

Output

Print a single integer, denoting the minimal sum of path from every fragment to the node with the emotion samples (a.k.a. node 𝑃).

As a reminder, if there are multiple fragments at the same node, the distance from that node to 𝑃 needs to be counted multiple times as well.

如果去掉噁心的建圖邏輯,題意就是給一顆樹並給樹上的一些點賦上值,現在要求一個根使得根到所有點的加權路徑和最小,做法有很多,最簡單的做法就是先隨便選一個點當根,然後不斷嘗試調整即可,注意這道題不需要根據題意顯式的把圖給建出來,標程用了一種比較trick的做法來維護了每次調整根後的子節點的狀態。

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
#include <cstring>
#include <unordered_map>
#include <map>

using namespace std;

typedef long long ll;
typedef vector<int> vci;
typedef pair<int, int> pii;
template <typename T> void UpdateMax(T& a, T b) {if (a < b) a = b;}
template <typename T> void UpdateMin(T& a, T b) {if (a > b) a = b;}
template<typename T>
inline void read(T &x)
{
    x = 0; char c = getchar(); int flag = 1;
    while(!isdigit(c)) {if (c == '-') flag = -1; c = getchar();}
    while(isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
    x *= flag;
}
template <typename T, typename V> void Print(const pair<T, V>& x) { cout<<x.first<<" @ "<<x.second<<" | "; }
template <typename T> void Print(const T& x) { cout<<x<<" ";  }
template <typename T> void Pcon(const T& x) { cout<<"\nsize: "<<x.size()<<endl; for (const auto& item : x) Print(item); }
const int N = 5005;
int n, x, f[N][N], pre[N], total[N];
ll Count[N], ans;
int main()
{
    read(n);
    for (int i = 0; i < n ;i++)
    {
        read(x);
        UpdateMax(x, 1);
        Count[x]++;
    }
    for (int i = 1; i < N; i++)
    {
        memcpy(f[i], f[i-1], sizeof(f[i]));
        pre[i] = 1;
        for (int j = 2, p = i; j <= i; j++)
        {
            while (p % j == 0)
            {
                f[i][j]++;
                p /= j;
            }
            if (f[i][j]) pre[i] = j;
            ans += f[i][j] * Count[i];
        }
    }
    for (int i = 1; i < N; i++)
    {
        if (!Count[i]) continue;
        total[pre[i]] += Count[i];
    }
    int temp = max_element(total + 1, total + N) - total;
    while (total[temp] && temp > 1)
    {
        if (total[temp] <= n/2) break;
        ans += n - 2*total[temp];
        memset(total, 0, sizeof(total));
        for (int i = 1; i < N; i++)
        {
            if (pre[i] != temp)
            {
                pre[i] = -1;
                continue;
            }
            f[i][pre[i]]--;
            while (!f[i][pre[i]] && pre[i] != 1) pre[i]--;
            if (pre[i] != 1)
            {
                total[pre[i]] += Count[i];
            }
        }
        temp = max_element(total + 1, total + N) - total;
    }
    cout<<ans<<endl;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章