mr_dot_convict

155E-Double-profiles-codeforces-mr.convict

Jul 16th, 2019
124
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.41 KB | None | 0 0
  1. // Hack it and have it ;) //
  2. /*author* Priyanshu Shrivastav (from IIT Palakkad) *
  3.  * *_ __ ___  _ ______ ___  _ ____   ___  ___| |_  *
  4.  * | '_ ` _ \| '__/ __/ _ \| '_ \ \ / / |/ __| __| *
  5.  * | | | | | | | | (_| (_) | | | \ V /| | (__| |_  *
  6.  * |_| |_| |_|_|(_)___\___/|_| |_|\_/ |_|\___|\__| *
  7. When I wrote this, only God and I understood what I was doing
  8.  ** * * * * * * * Now, only God knows * * * * * * */
  9. #include      <bits/stdc++.h>
  10. #include      <ext/pb_ds/assoc_container.hpp>
  11. #include      <ext/pb_ds/tree_policy.hpp>
  12. using namespace std;
  13. using namespace __gnu_pbds;
  14. #pragma GCC   optimize ("Ofast")
  15. #pragma GCC   optimize ("unroll-loops")
  16. #pragma GCC   target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
  17.  
  18. #define IOS   ios_base::sync_with_stdio(false); cin.tie (nullptr)
  19. #define PREC  cout.precision (10); cout << fixed
  20. #define x     first
  21. #define y     second
  22. #define bg(x) " [ " << #x << " : " << (x) << " ] "
  23. #define un(x) sort(x.begin(), x.end()), \
  24.               x.erase(unique(x.begin(), x.end()), x.end())
  25. using   ll  = long long;
  26. using   ull = unsigned long long;
  27. using   ff  = long double;
  28. using   pii = pair<int,int>;
  29. using   pil = pair<int,ll>;
  30. typedef tree
  31. < int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update>
  32. ordered_set;
  33.  
  34. struct chash {
  35.    int operator()(pii x) const { return x.x*31 + x.y; }
  36. };
  37. gp_hash_table <pii, int, chash> mp;
  38.  
  39. seed_seq seq{
  40.    (uint64_t) chrono::duration_cast<chrono::nanoseconds>
  41.       (chrono::high_resolution_clock::now().time_since_epoch()).count(),
  42.       (uint64_t) __builtin_ia32_rdtsc(),
  43.       (uint64_t) (uintptr_t) make_unique<char>().get()
  44. };
  45. mt19937 rng(seq); //uniform_int_distribution<int> (l, h)(rng); //[low, high]
  46.  
  47. #define debug(args...) { \
  48.    /* WARNING : do NOT compile this debug func calls with following flags: // \
  49.     * // -D_GLIBCXX_DEBUG -D_GLIBCXX_DEBUG_PEDANTIC -D_FORTIFY_SOURCE=2*/ \
  50.    string _s = #args; replace(_s.begin(), _s.end(), ',', ' ');\
  51.    stringstream _ss(_s); \
  52.    istream_iterator<string> _it(_ss); err(_it, args); \
  53. }
  54. void err(istream_iterator<string> it) {
  55.    it->empty(); cerr << " (Line : " << __LINE__ << ")" << '\n';
  56. }
  57. template<typename T, typename... Args>
  58. void err(istream_iterator<string> it, T a, Args... args) {
  59.    cerr << fixed << setprecision(15)
  60.       << " [ " <<  *it << " : " << a  << " ] "<< ' ';
  61.    err(++it, args...);
  62. }
  63. /*****************************************************************************/
  64.  
  65. struct polyhash {
  66.    using ull = unsigned long long;
  67.    static const int Mod = (int)1e9 + 123;
  68.    static vector <int> pow_int;
  69.    static vector <ull> pow_ull;
  70.    static int p; // take p such that a[i] < p < Mod, gcd(p, Mod) = 1
  71.    static int gen_base (const int l, const int r) {
  72.       int base = uniform_int_distribution<int>(l + 1, r) (rng);
  73.       return base % 2 == 0 ? base - 1 : base;
  74.    }
  75.    const int sz;
  76.  
  77.    vector <int> s;
  78.    vector <int> pref_int;
  79.    vector <ull> pref_ull;
  80.  
  81.    void encode(const vector <int>&st) {
  82.       s.assign(sz, 0);
  83.       for (int i = 0; i < sz; ++i) s[i] = st[i];
  84.    }
  85.  
  86.    static void calc_pow(int mx_len) {
  87.       while ((int)pow_int.size() <= mx_len) { // calc powers
  88.          pow_int.push_back(int(1ll * pow_int.back() * p % Mod));
  89.          pow_ull.push_back(pow_ull.back() * p);
  90.       }
  91.    }
  92.  
  93.    polyhash (const vector <int>&st) : sz((int)st.size())
  94.    {
  95.       encode(st);
  96.       pref_int.assign(sz + 1u, 0);
  97.       pref_ull.assign(sz + 1u, 0);
  98.       assert(p < Mod);
  99.  
  100.       calc_pow(sz + 1);
  101.  
  102.       for (int i = 0; i < sz; ++i) {
  103.          assert(p > s[i]);
  104.          pref_int[i] = int(1ll*s[i]*pow_int[i] % Mod);
  105.          pref_int[i] = (pref_int[i] + (i > 0 ? pref_int[i - 1] : 0)) % Mod;
  106.          pref_ull[i] = s[i]*pow_ull[i] + (i > 0 ? pref_ull[i - 1] : 0);
  107.       }
  108.    }
  109.  
  110.    inline pair <int, ull> operator()
  111.       (const int pos, const int len, const int mx_len = -1) const
  112.       {
  113.          int hash_int = pref_int[pos + len - 1];
  114.          ull hash_ull = pref_ull[pos + len - 1];
  115.          if (pos != 0) {
  116.             hash_int = (hash_int - pref_int[pos - 1] + Mod) % Mod;
  117.             hash_ull = hash_ull - pref_ull[pos - 1];
  118.          }
  119.          if (mx_len != -1) { // for direct comparison between prefixes
  120.             //else multiply with opposite powers
  121.             assert (mx_len < (int)pow_int.size());
  122.             hash_int = int(1ll*hash_int*pow_int[mx_len - (pos+len-1)] % Mod);
  123.             hash_ull *= pow_ull[mx_len - (pos+len-1)];
  124.          }
  125.          return make_pair(hash_int, hash_ull);
  126.       }
  127.    //string a; polyhash hash_a(a); if (hash_a(i, len, sz) == hash_b(j, len, sz))
  128.    //indexing from 0, len >= 1
  129. };
  130.  
  131. int polyhash::p = polyhash::gen_base((int)1e6 + 10, polyhash::Mod);
  132. vector <int> polyhash::pow_int{1};
  133. vector <ull> polyhash::pow_ull{1};
  134. // int polyhash::p = 31; // 31 for [a ... z], 53 for [a..z, A..Z]
  135.  
  136. const int N = (int)1e6 + 10;
  137. vector <pair <int, ull>> hashes;
  138. vector <vector <int>> adj;
  139. int n, m;
  140. ll cnt = 0;
  141. bool empty[N];
  142. int mxpw = 0;
  143. vector <int> idx;
  144.  
  145. void solve() {
  146.    for (int i = 1; i <= n; ++i) {
  147.       adj[i].push_back(i);
  148.       mxpw = max(mxpw, (int)adj[i].size() + 1);
  149.    }
  150.    polyhash::calc_pow(mxpw + 1);
  151.  
  152.    for (int i = 1; i <= 2*n; ++i) {
  153.       sort(adj[i].begin(), adj[i].end());
  154.    }
  155.  
  156.    hashes.clear();
  157.    for (int i = 1; i <= 2*n; ++i) {
  158.       if (adj[i].size() != 0) {
  159.          polyhash hash(adj[i]);
  160.          hashes.push_back(hash(0, (int)adj[i].size(), mxpw));
  161.       }
  162.       else hashes.push_back(make_pair(0, 0));
  163.    }
  164.  
  165.    sort(hashes.begin(), hashes.end());
  166.  
  167.    pair <int, ull> cur_hash = make_pair(-1, 0);
  168.    int cur_cnt = 0;
  169.    for (int i = 0; i < (int)hashes.size(); ++i) {
  170.       if (!cur_cnt) {
  171.          cur_hash = hashes[i];
  172.          ++cur_cnt;
  173.       }
  174.       else {
  175.          if (cur_hash == hashes[i]) {
  176.             ++cur_cnt;
  177.          }
  178.          else {
  179.             cnt += (1ll* (cur_cnt) * (cur_cnt - 1))/2;
  180.             cur_hash = hashes[i];
  181.             cur_cnt = 1;
  182.          }
  183.       }
  184.    }
  185.    cnt += (1ll* (cur_cnt) * (cur_cnt - 1))/2;
  186.    cout << cnt << '\n';
  187. }
  188.  
  189. void read() {
  190.    cin >> n >> m;
  191.    adj.assign(2*n + 1, vector <int> ());
  192.    for (int i = 0; i < m; ++i) {
  193.       int u, v;
  194.       cin >> u >> v;
  195.       adj[u].push_back(v);
  196.       adj[v].push_back(u);
  197.       adj[u + n].push_back(v);
  198.       adj[v + n].push_back(u);
  199.    }
  200. }
  201.  
  202. signed main() {
  203.    IOS; PREC;
  204.    read(), solve();
  205.  
  206.    return EXIT_SUCCESS;
  207. }
Add Comment
Please, Sign In to add comment