Codeforcesの1322C - インスタントラーメン(数学)

トピックリンク

問題の意味

これは、二部グラフ、両側のn個の点のそれぞれ、m個のエッジの総数、N、M≤5E5を与える。重量のドットの右\(C_I \)を Sだけ左点を含む点集合、Nの定義(のために、 S)右に隣接する全てのこのセットポイント設定点の点であり、F(S)は、すべての可能なF(S)は、最大公約数であり、これらの点およびQの重量です。

思考

彼らは、ポイントに元の重量と重量の新しい値を縮小するように、それらはN(S)で同時に発生しなければならないことを示し、それらが一致している点に対応する左場合は、右側の点の数を考慮する。凝縮を点0度に再びそれらの点を除去した後、次の証明GCD答えは残りの点の重みである。後述する(C_I \)\上述した処理されました。

このとき、答えは、配置されたグラムであるGの真の価値を与えることを、明らかにG.すべてのF(S)で割り切れる答え\(G | G \)を提供する。\(Gは\ G×K =)ので、すべてのこと。\(C_I \ )で割った\(G \) 仮定>(\ Kを1に\)がある\(C_J \) そう\(K \ C_J NMID \) ポイントの全てに隣接して配置された点を構成しません集合S「U、N(S放置ポイントの全集」)は、他のポイントがない場合ので、ポイントがあるため、矛盾している縮小された、含まれるだけでなく、右の点セット点j含まれる\ (K | F(U-)、K \ C_J NMID \) そう\(K \ NMID F(U - S「)\) 競合解決ように。\(K = 1、G = G \。)

コード

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define inc(i, l, r) for (int i = l; i <= r; i++)

const int maxn = 5e5 + 5;

int t, n, m, u, v;
ll c[maxn];
vector<int> g[maxn];

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    cin >> t;
    while (t--) {
        cin >> n >> m;
        inc(i, 0, n - 1) vector<int>().swap(g[i]);
        inc(i, 0, n - 1) cin >> c[i];
        inc(i, 0, m - 1) {
            cin >> u >> v;
            u--, v--;
            g[v].push_back(u);
        }
        inc(i, 0, n - 1) sort(g[i].begin(), g[i].end());
        vector<int> id(n);
        iota(id.begin(), id.end(), 0);
        sort(id.begin(), id.end(), [&](int a, int b) { return g[a] < g[b]; });
        ll res = 0;
        for (int i = 0, j; i < n; i = j) {
            ll sum = 0;
            j = i;
            while (j < n && g[id[i]] == g[id[j]]) {
                sum += c[id[j]];
                j++;
            }
            if (g[id[i]].size()) res = __gcd(res, sum);
        }
        cout << res << "\n";
    }
}

おすすめ

転載: www.cnblogs.com/hs-zlq/p/12566671.html