結果
問題 | No.2985 May Count Induced C4 Subgraphs |
ユーザー |
|
提出日時 | 2024-12-10 01:05:11 |
言語 | C++23 (gcc 13.3.0 + boost 1.87.0) |
結果 |
RE
|
実行時間 | - |
コード長 | 18,459 bytes |
コンパイル時間 | 4,239 ms |
コンパイル使用メモリ | 297,832 KB |
実行使用メモリ | 5,248 KB |
最終ジャッジ日時 | 2024-12-10 01:05:19 |
合計ジャッジ時間 | 7,152 ms |
ジャッジサーバーID (参考情報) |
judge2 / judge4 |
(要ログイン)
ファイルパターン | 結果 |
---|---|
other | AC * 6 RE * 16 |
ソースコード
#line 2 "/root/AtCoder/Halc-Library/Template/Template.hpp"#include <bits/stdc++.h>using namespace std;#line 8 "/root/AtCoder/Halc-Library/Template/InOut.hpp"inline void scan() {}inline void scan(int32_t &a) { std::cin >> a; }inline void scan(uint32_t &a) { std::cin >> a; }inline void scan(int64_t &a) { std::cin >> a; }inline void scan(uint64_t &a) { std::cin >> a; }inline void scan(char &a) { std::cin >> a; }inline void scan(float &a) { std::cin >> a; }inline void scan(double &a) { std::cin >> a; }inline void scan(long double &a) { std::cin >> a; }inline void scan(std::vector<bool> &vec) {for (int32_t i = 0; i < vec.size(); i++) {int a;scan(a);vec[i] = a;}}inline void scan(std::string &a) { std::cin >> a; }template <class T>inline void scan(std::vector<T> &vec);template <class T, size_t size>inline void scan(std::array<T, size> &vec);template <class T, class L>inline void scan(std::pair<T, L> &p);template <class T, size_t size>inline void scan(T (&vec)[size]);template <class T>inline void scan(std::vector<T> &vec) {for (auto &i : vec) scan(i);}template <class T>inline void scan(std::deque<T> &vec) {for (auto &i : vec) scan(i);}template <class T, size_t size>inline void scan(std::array<T, size> &vec) {for (auto &i : vec) scan(i);}template <class T, class L>inline void scan(std::pair<T, L> &p) {scan(p.first);scan(p.second);}template <class T, size_t size>inline void scan(T (&vec)[size]) {for (auto &i : vec) scan(i);}template <class T>inline void scan(T &a) {std::cin >> a;}inline void in() {}template <class Head, class... Tail>inline void in(Head &head, Tail &...tail) {scan(head);in(tail...);}inline void print() { std::cout << ' '; }inline void print(const bool &a) { std::cout << a; }inline void print(const int32_t &a) { std::cout << a; }inline void print(const uint32_t &a) { std::cout << a; }inline void print(const int64_t &a) { std::cout << a; }inline void print(const uint64_t &a) { std::cout << a; }inline void print(const char &a) { std::cout << a; }inline void print(const char a[]) { std::cout << a; }inline void print(const float &a) { std::cout << a; }inline void print(const double &a) { std::cout << a; }inline void print(const long double &a) { std::cout << a; }inline void print(const std::string &a) {for (auto &&i : a) print(i);}template <class T>inline void print(const std::vector<T> &vec);template <class T, size_t size>inline void print(const std::array<T, size> &vec);template <class T, class L>inline void print(const std::pair<T, L> &p);template <class T, size_t size>inline void print(const T (&vec)[size]);template <class T>inline void print(const std::vector<T> &vec) {if (vec.empty()) return;print(vec[0]);for (auto i = vec.begin(); ++i != vec.end();) {std::cout << ' ';print(*i);}}template <class T>inline void print(const std::deque<T> &vec) {if (vec.empty()) return;print(vec[0]);for (auto i = vec.begin(); ++i != vec.end();) {std::cout << ' ';print(*i);}}template <class T, size_t size>inline void print(const std::array<T, size> &vec) {print(vec[0]);for (auto i = vec.begin(); ++i != vec.end();) {std::cout << ' ';print(*i);}}template <class T, class L>inline void print(const std::pair<T, L> &p) {print(p.first);std::cout << ' ';print(p.second);}template <class T, size_t size>inline void print(const T (&vec)[size]) {print(vec[0]);for (auto i = vec; ++i != end(vec);) {std::cout << ' ';print(*i);}}template <class T>inline void print(const T &a) {std::cout << a;}inline void out() { std::cout << '\n'; }template <class T>inline void out(const T &t) {print(t);std::cout << '\n';}template <class Head, class... Tail>inline void out(const Head &head, const Tail &...tail) {print(head);std::cout << ' ';out(tail...);}inline void Yes(bool i = true) { out(i ? "Yes" : "No"); }inline void No(bool i = true) { out(i ? "No" : "Yes"); }inline void Takahashi(bool i = true) { out(i ? "Takahashi" : "Aoki"); }inline void Aoki(bool i = true) { out(i ? "Aoki" : "Takahashi"); }inline void Alice(bool i = true) { out(i ? "Alice" : "Bob"); }inline void Bob(bool i = true) { out(i ? "Bob" : "Alice"); }inline void First(bool i = true) { out(i ? "First" : "Second"); }inline void Second(bool i = true) { out(i ? "Second" : "First"); }inline void Possible(bool i = true) { out(i ? "Possible" : "Impossible"); }inline void Impossible(bool i = true) { out(i ? "Impossible" : "Possible"); }inline void fls() { std::flush(std::cout); }struct IOsetup {IOsetup() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);std::cout << std::fixed << std::setprecision(16);}} iosetup;#line 9 "/root/AtCoder/Halc-Library/Template/Util.hpp"using ll = int64_t;using ld = long double;using ull = uint64_t;using uint = uint32_t;using pll = std::pair<ll, ll>;using pii = std::pair<int32_t, int32_t>;using vl = std::vector<ll>;using vvl = std::vector<std::vector<ll>>;using pdd = std::pair<ld, ld>;using tuplis = std::array<ll, 3>;template <class T>using pq = std::priority_queue<T, std::vector<T>, std::greater<T>>;constexpr ll LINF = (1LL << 62) - (1LL << 31);constexpr int32_t INF = INT_MAX >> 1;constexpr ll MINF = 1LL << 40;constexpr ld DINF = std::numeric_limits<ld>::infinity();constexpr int32_t MODD = 1000000007;constexpr int32_t MOD = 998244353;constexpr ld EPS = 1e-9;constexpr ld PI = 3.1415926535897932;const ll four[] = {0, 1, 0, -1, 0};const ll eight[] = {0, 1, 1, 0, -1, -1, 1, -1, 0};template <class T>bool chmin(T &a, const T &b) {if (a > b) {a = b;return true;} elsereturn false;}template <class T>bool chmax(T &a, const T &b) {if (a < b) {a = b;return true;} elsereturn false;}template <class T>ll sum(const T &a) {return accumulate(std::begin(a), std::end(a), 0LL);}template <class T>ld dsum(const T &a) {return accumulate(std::begin(a), std::end(a), 0.0L);}template <class T>auto min(const T &a) {return *min_element(std::begin(a), std::end(a));}template <class T>auto max(const T &a) {return *max_element(std::begin(a), std::end(a));}#line 1 "/root/AtCoder/Halc-Library/Template/Macro.hpp"#define _overload3(_1, _2, _3, name, ...) name#define _overload4(_1, _2, _3, _4, name, ...) name#define _rep1(i, n) for (int64_t i = 0; i < (n); i++)#define _rep2(i, a, b) for (int64_t i = (a); i < (b); i++)#define _rep3(i, a, b, c) for (int64_t i = (a); i < (b); i += (c))#define rep(...) _overload4(__VA_ARGS__, _rep3, _rep2, _rep1)(__VA_ARGS__)#define _rrep1(i, n) for (int64_t i = (n) - 1; i >= 0; i--)#define _rrep2(i, a, b) for (int64_t i = (b) - 1; i >= (a); i--)#define rrep(...) _overload3(__VA_ARGS__, _rrep2, _rrep1)(__VA_ARGS__)#define each(i, ...) for (auto&& i : __VA_ARGS__)#define all(i) std::begin(i), std::end(i)#define rall(i) std::rbegin(i), std::rend(i)#define len(x) ((int64_t)(x).size())#define fi first#define se second#define uniq(x) x.erase(unique(all(x)), std::end(x))#define vec(type, name, ...) vector<type> name(__VA_ARGS__);#define vv(type, name, h, ...) std::vector<std::vector<type>> name(h, std::vector<type>(__VA_ARGS__));#define INT(...) int32_t __VA_ARGS__; in(__VA_ARGS__)#define LL(...) int64_t __VA_ARGS__; in(__VA_ARGS__)#define ULL(...) uint64_t __VA_ARGS__; in(__VA_ARGS__)#define STR(...) std::string __VA_ARGS__; in(__VA_ARGS__)#define CHR(...) char __VA_ARGS__; in(__VA_ARGS__)#define LD(...) long double __VA_ARGS__; in(__VA_ARGS__)#define VEC(type, name, size) std::vector<type> name(size); in(name)#define VV(type, name, h, w) std::vector<std::vector<type>> name(h, std::vector<type>(w)); in(name)#line 3 "/root/AtCoder/Halc-Library/Modint/Modint.hpp"#line 6 "/root/AtCoder/Halc-Library/Modint/Modint.hpp"template <uint64_t Mod>struct Modint {uint64_t x;constexpr Modint() noexcept { x = 0; }constexpr Modint(int64_t val) noexcept {x = (val < 0 ? val % (int64_t)(Mod) + Mod : val % Mod);}inline uint64_t _get_mod(uint64_t val) noexcept {const static uint64_t m_inv = (-1ULL) / Mod + 1;uint64_t ret = ((unsigned __int128)(val)*m_inv) >> 64;uint64_t pro = ret * Mod;return (val - pro + (val < pro ? Mod : 0));}friend std::ostream &operator<<(std::ostream &os, Modint &b) noexcept {return os << b.x;}friend std::istream &operator>>(std::istream &is, Modint &b) noexcept {return is >> b.x;}constexpr uint64_t val() noexcept { return x; }constexpr Modint operator+() noexcept { return (*this); }constexpr Modint operator-() noexcept { return Modint() - (*this); }friend Modint operator+(const Modint lhs, const Modint rhs) noexcept {return Modint(lhs) += rhs;}friend Modint operator-(const Modint lhs, const Modint rhs) noexcept {return Modint(lhs) -= rhs;}friend Modint operator*(const Modint lhs, const Modint rhs) noexcept {return Modint(lhs) *= rhs;}friend Modint operator/(const Modint lhs, const Modint rhs) {return Modint(lhs) /= rhs;}constexpr Modint &operator+=(const Modint rhs) noexcept {x += rhs.x;if (x >= Mod) x -= Mod;return *this;}constexpr Modint &operator-=(const Modint rhs) noexcept {if (x < rhs.x) x += Mod;x -= rhs.x;return *this;}constexpr Modint &operator*=(const Modint rhs) noexcept {x = _get_mod(x * rhs.x);return *this;}friend bool operator==(const Modint lhs, const Modint rhs) noexcept {return lhs.x == rhs.x;}friend bool operator!=(const Modint lhs, const Modint rhs) noexcept {return rhs.x != rhs.x;}constexpr Modint &operator/=(Modint rhs) { return (*this) *= rhs.inv(); }constexpr Modint inv() {int64_t a = (*this).x, b = get_mod();assert(a != 0);int64_t s = b, t = a;int64_t m0 = 0, m1 = 1;while (t) {int64_t u = s / t;s -= t * u;m0 -= m1 * u;int64_t tmp = s;s = t;t = tmp;tmp = m0;m0 = m1;m1 = tmp;}assert(s == 1);if (m0 < 0) m0 += b;return Modint(m0);}constexpr Modint pow(uint64_t x) noexcept {Modint ret = 1;Modint bin = (*this);while (x) {if (x & 1) ret *= bin;bin *= bin;x >>= 1;}return ret;}static uint64_t get_mod() noexcept { return Mod; }};template <int64_t id>struct ArbitraryModint {uint64_t x;static uint64_t &mod() noexcept {static uint64_t Mod = 0;return Mod;}constexpr ArbitraryModint() noexcept { x = 0; }constexpr ArbitraryModint(int64_t val) noexcept {x = (val < 0 ? val % (int64_t)(get_mod()) + get_mod(): val % get_mod());}inline uint64_t _get_mod(uint64_t val) noexcept {const static uint64_t m_inv = (-1ULL) / get_mod() + 1;uint64_t ret = ((unsigned __int128)(val)*m_inv) >> 64;uint64_t pro = ret * get_mod();return (val - pro + (val < pro ? get_mod() : 0));}friend std::ostream &operator<<(std::ostream &os,ArbitraryModint &b) noexcept {return os << b.x;}friend std::istream &operator>>(std::istream &is,ArbitraryModint &b) noexcept {return is >> b.x;}constexpr uint64_t val() noexcept { return x; }constexpr ArbitraryModint operator+() noexcept { return (*this); }constexpr ArbitraryModint operator-() noexcept {return ArbitraryModint() - (*this);}friend ArbitraryModint operator+(const ArbitraryModint lhs,const ArbitraryModint rhs) noexcept {return ArbitraryModint(lhs) += rhs;}friend ArbitraryModint operator-(const ArbitraryModint lhs,const ArbitraryModint rhs) noexcept {return ArbitraryModint(lhs) -= rhs;}friend ArbitraryModint operator*(const ArbitraryModint lhs,const ArbitraryModint rhs) noexcept {return ArbitraryModint(lhs) *= rhs;}friend ArbitraryModint operator/(const ArbitraryModint lhs,const ArbitraryModint rhs) {return ArbitraryModint(lhs) /= rhs;}constexpr ArbitraryModint &operator+=(const ArbitraryModint rhs) noexcept {x += rhs.x;if (x >= mod()) x -= mod();return *this;}constexpr ArbitraryModint &operator-=(const ArbitraryModint rhs) noexcept {if (x < rhs.x) x += mod();x -= rhs.x;return *this;}constexpr ArbitraryModint &operator*=(const ArbitraryModint rhs) noexcept {x = _get_mod(x * rhs.x);return *this;}friend bool operator==(const ArbitraryModint lhs,const ArbitraryModint rhs) noexcept {return lhs.x == rhs.x;}friend bool operator!=(const ArbitraryModint lhs,const ArbitraryModint rhs) noexcept {return rhs.x != rhs.x;}constexpr ArbitraryModint &operator/=(ArbitraryModint rhs) {return (*this) *= rhs.inv();}constexpr ArbitraryModint inv() {int64_t a = (*this).x, b = get_mod();assert(a != 0);int64_t s = b, t = a;int64_t m0 = 0, m1 = 1;while (t) {int64_t u = s / t;s -= t * u;m0 -= m1 * u;int64_t tmp = s;s = t;t = tmp;tmp = m0;m0 = m1;m1 = tmp;}assert(s == 1);if (m0 < 0) m0 += b;return ArbitraryModint(m0);}constexpr ArbitraryModint pow(uint64_t x) noexcept {ArbitraryModint ret = 1;ArbitraryModint bin = (*this);while (x) {if (x & 1) ret *= bin;bin *= bin;x >>= 1;}return ret;}static void set_mod(const uint64_t x) noexcept { mod() = x; }static uint64_t get_mod() noexcept { return mod(); }};template <uint64_t N>inline void scan(Modint<N> &a) {std::cin >> a.x;}template <int64_t id>inline void scan(ArbitraryModint<id> &a) {std::cin >> a.x;}template <uint64_t N>inline void print(Modint<N> a) {std::cout << a.x;}template <int64_t id>inline void print(ArbitraryModint<id> a) {std::cout << a.x;}#line 3 "main.cpp"using mint=Modint<MOD>;class CountingC4 {private:int V, threshold;vector<vector<int> > G;vector<vector<array<int, 2> > > memo;vector<int> flag1, flag2;void process_high_degree(long long& ans){for(int i = 0; i < V; ++i){if((int)G[i].size() <= threshold) continue;for(const int u : G[i]){if(u > i) flag1[u] = 1;flag2[u] = 1;}for(int j = 0; j < i; ++j){if((int)G[j].size() > threshold) continue;long long cnt1 = 0, cnt2 = 0;for(const int u : G[j]){if(u < j || !flag2[u]) continue;if((int)G[u].size() > threshold) ++cnt1;else ++cnt2;}ans += (cnt1 + cnt2) * (cnt1 + cnt2 - 1) / 2;}for(int j = i + 1; j < V; ++j){long long cnt = 0;for(const int u : G[j]){if(flag1[u]) ++cnt;}ans += cnt * (cnt - 1) / 2;}for(const int u : G[i]) flag1[u] = flag2[u] = 0;}}void process_low_degree(long long& ans){for(int i = 0; i < V; ++i){if((int)G[i].size() > threshold) continue;for(const int u : G[i]){for(const int v : G[i]){if(v > u) memo[u].push_back({i, v});}}}for(int i = 0; i < V; ++i){for(const auto& e : memo[i]){if(e[0] < i) ++flag1[e[1]];else ++flag2[e[1]];}for(const auto& e : memo[i]){ans += (long long)(flag1[e[1]] + 2 * flag2[e[1]] - 1) * flag1[e[1]] / 2;flag1[e[1]] = flag2[e[1]] = 0;}}}public:CountingC4(const int node_size): V(node_size), threshold(0), G(V), memo(V), flag1(V, 0), flag2(V, 0){}void add_edge(const int u, const int v){G[u].push_back(v), G[v].push_back(u);++threshold;}long long solve(){threshold = floor(sqrt(2 * threshold)) / 2;long long ans = 0;process_high_degree(ans);process_low_degree(ans);return ans;}};void solve() {LL(N,M);if(N<=3){out(0,0);return;}vec(bitset<200000>,gr,N);CountingC4 gr2(N);vec(pll,edge,M);vec(ll,cnt,N,0);rep(i,M){LL(U,V);edge[i]={U-1,V-1};gr2.add_edge(U-1,V-1);cnt[U-1]++;cnt[V-1]++;gr[U-1][V-1]=1;gr[V-1][U-1]=1;}mint ans=0;ans=mint(N)*(N-1)*(N-2)*(N-3)/24;ans-=mint(M)*(N-2)*(N-3)/2;mint adj=0;rep(i,N){adj+=cnt[i]*(cnt[i]-1)/2;}ans+=adj*(N-3);ans+=(mint(M)*(M-1)/2-adj);vec(ll,common,M);rep(i,M){common[i]=(gr[edge[i].fi]&gr[edge[i].se]).count();}mint tri=0;mint nt=0;mint four=0;mint five=0;rep(i,M){tri+=common[i];nt+=(cnt[edge[i].fi]-1)*(cnt[edge[i].se]-1)-common[i];four+=common[i]*(cnt[edge[i].fi]+cnt[edge[i].se]-4);five+=common[i]*(common[i]-1)/2;}ans-=tri/3*(N-3);ans-=nt;rep(i,N){ans-=cnt[i]*(cnt[i]-1)*(cnt[i]-2)/6;}ans+=four/2;ans+=gr2.solve()*mint(2)/3;ans-=five*mint(2)/3;out(mint(-1)/3,ans);}int main() { solve(); }