QOJ.ac
QOJ
ID | 题目 | 提交者 | 结果 | 用时 | 内存 | 语言 | 文件大小 | 提交时间 | 测评时间 |
---|---|---|---|---|---|---|---|---|---|
#195135 | #7514. Clique Challenge | ucup-team1951# | WA | 103ms | 3864kb | C++17 | 10.1kb | 2023-10-01 01:08:58 | 2023-10-01 01:08:58 |
Judging History
answer
// https://judge.yosupo.jp/submission/129199
#line 2 "graph/enumerate_cliques.hpp"
/**
* @file enumerate_cliques.hpp
* @brief Enumerate all cliques
* @author hitonanode
* @date 2023/03/10
*/
#include <algorithm>
#include <cassert>
#include <numeric>
#include <queue>
#include <utility>
#include <vector>
// Complexity: O(2 ** sqrt(2m) * n)
// p.15, https://www.slideshare.net/wata_orz/ss-12131479
struct enumerate_cliques {
std::vector<std::vector<int>> to;
std::vector<std::pair<int, int>> edges;
int n() const { return to.size(); }
int m() const { return edges.size(); }
enumerate_cliques(int n_) : to(n_) {}
void add_bi_edge(int u, int v) {
assert(0 <= u and u < n());
assert(0 <= v and v < n());
if (u != v) edges.emplace_back(std::minmax(u, v));
}
// Build `to`
void precalc() {
std::sort(edges.begin(), edges.end());
edges.erase(std::unique(edges.begin(), edges.end()), edges.end());
for (auto &vec : to) vec.clear();
for (auto [u, v] : edges) to.at(u).push_back(v), to.at(v).push_back(u);
for (auto &vec : to) std::sort(vec.begin(), vec.end());
}
template <class F>
void bruteforce(const std::vector<int> &cand_vs, int prefix_use, F op) const {
const int k = cand_vs.size();
const int mask_all = (1 << k) - 1;
std::vector<int> ok_masks(k, mask_all);
for (int i = 0; i < k; ++i) {
for (int j = 0; j < i; ++j) {
int u = cand_vs.at(i), v = cand_vs.at(j);
if (!std::binary_search(to.at(u).cbegin(), to.at(u).cend(), v)) {
ok_masks.at(i) &= ~(1 << j), ok_masks.at(j) &= ~(1 << i);
}
}
}
std::vector<int> seq;
if (prefix_use >= 0) seq.push_back(prefix_use);
seq.reserve(seq.size() + k);
auto rec = [&](auto &&self, int now, const int last_mask) -> void {
op(seq);
seq.push_back(-1);
for (int i = now; i < k; ++i) {
if ((last_mask >> i) & 1) {
seq.back() = cand_vs.at(i);
self(self, i + 1, last_mask & ok_masks.at(i));
}
}
seq.pop_back();
};
rec(rec, 0, mask_all);
return;
}
template <class F> void run(F op) {
precalc();
std::vector<int> deg(n()), is_alive(n(), 1);
using P = std::pair<int, int>;
std::priority_queue<P, std::vector<P>, std::greater<P>> pq;
for (int i = 0; i < n(); ++i) deg.at(i) = to.at(i).size(), pq.emplace(deg.at(i), i);
int rem_n = n(), rem_m = m();
std::vector<int> cand_vs;
while (!pq.empty()) {
auto [di, i] = pq.top();
pq.pop();
if (deg.at(i) != di) continue;
cand_vs.clear();
if (di * di > rem_m * 2) { // Avoid "deg[i] = 0" case
for (int i = 0; i < n(); ++i) {
if (is_alive.at(i)) cand_vs.push_back(i);
}
bruteforce(cand_vs, -1, op);
break;
}
for (int j : to.at(i)) {
if (is_alive.at(j)) cand_vs.push_back(j);
}
bruteforce(cand_vs, i, op);
--rem_n, deg.at(i) = 0, is_alive.at(i) = 0;
for (int j : cand_vs) --rem_m, --deg.at(j), pq.emplace(deg.at(j), j);
}
}
};
#line 2 "modint.hpp"
#include <iostream>
#include <set>
#line 5 "modint.hpp"
template <int md> struct ModInt {
#if __cplusplus >= 201402L
#define MDCONST constexpr
#else
#define MDCONST
#endif
using lint = long long;
MDCONST static int mod() { return md; }
static int get_primitive_root() {
static int primitive_root = 0;
if (!primitive_root) {
primitive_root = [&]() {
std::set<int> fac;
int v = md - 1;
for (lint i = 2; i * i <= v; i++)
while (v % i == 0) fac.insert(i), v /= i;
if (v > 1) fac.insert(v);
for (int g = 1; g < md; g++) {
bool ok = true;
for (auto i : fac)
if (ModInt(g).pow((md - 1) / i) == 1) {
ok = false;
break;
}
if (ok) return g;
}
return -1;
}();
}
return primitive_root;
}
int val_;
int val() const noexcept { return val_; }
MDCONST ModInt() : val_(0) {}
MDCONST ModInt &_setval(lint v) { return val_ = (v >= md ? v - md : v), *this; }
MDCONST ModInt(lint v) { _setval(v % md + md); }
MDCONST explicit operator bool() const { return val_ != 0; }
MDCONST ModInt operator+(const ModInt &x) const {
return ModInt()._setval((lint)val_ + x.val_);
}
MDCONST ModInt operator-(const ModInt &x) const {
return ModInt()._setval((lint)val_ - x.val_ + md);
}
MDCONST ModInt operator*(const ModInt &x) const {
return ModInt()._setval((lint)val_ * x.val_ % md);
}
MDCONST ModInt operator/(const ModInt &x) const {
return ModInt()._setval((lint)val_ * x.inv().val() % md);
}
MDCONST ModInt operator-() const { return ModInt()._setval(md - val_); }
MDCONST ModInt &operator+=(const ModInt &x) { return *this = *this + x; }
MDCONST ModInt &operator-=(const ModInt &x) { return *this = *this - x; }
MDCONST ModInt &operator*=(const ModInt &x) { return *this = *this * x; }
MDCONST ModInt &operator/=(const ModInt &x) { return *this = *this / x; }
friend MDCONST ModInt operator+(lint a, const ModInt &x) {
return ModInt()._setval(a % md + x.val_);
}
friend MDCONST ModInt operator-(lint a, const ModInt &x) {
return ModInt()._setval(a % md - x.val_ + md);
}
friend MDCONST ModInt operator*(lint a, const ModInt &x) {
return ModInt()._setval(a % md * x.val_ % md);
}
friend MDCONST ModInt operator/(lint a, const ModInt &x) {
return ModInt()._setval(a % md * x.inv().val() % md);
}
MDCONST bool operator==(const ModInt &x) const { return val_ == x.val_; }
MDCONST bool operator!=(const ModInt &x) const { return val_ != x.val_; }
MDCONST bool operator<(const ModInt &x) const {
return val_ < x.val_;
} // To use std::map<ModInt, T>
friend std::istream &operator>>(std::istream &is, ModInt &x) {
lint t;
return is >> t, x = ModInt(t), is;
}
MDCONST friend std::ostream &operator<<(std::ostream &os, const ModInt &x) {
return os << x.val_;
}
MDCONST ModInt pow(lint n) const {
ModInt ans = 1, tmp = *this;
while (n) {
if (n & 1) ans *= tmp;
tmp *= tmp, n >>= 1;
}
return ans;
}
static std::vector<ModInt> facs, facinvs, invs;
MDCONST static void _precalculation(int N) {
int l0 = facs.size();
if (N > md) N = md;
if (N <= l0) return;
facs.resize(N), facinvs.resize(N), invs.resize(N);
for (int i = l0; i < N; i++) facs[i] = facs[i - 1] * i;
facinvs[N - 1] = facs.back().pow(md - 2);
for (int i = N - 2; i >= l0; i--) facinvs[i] = facinvs[i + 1] * (i + 1);
for (int i = N - 1; i >= l0; i--) invs[i] = facinvs[i] * facs[i - 1];
}
MDCONST ModInt inv() const {
if (this->val_ < std::min(md >> 1, 1 << 21)) {
if (facs.empty()) facs = {1}, facinvs = {1}, invs = {0};
while (this->val_ >= int(facs.size())) _precalculation(facs.size() * 2);
return invs[this->val_];
} else {
return this->pow(md - 2);
}
}
MDCONST ModInt fac() const {
while (this->val_ >= int(facs.size())) _precalculation(facs.size() * 2);
return facs[this->val_];
}
MDCONST ModInt facinv() const {
while (this->val_ >= int(facs.size())) _precalculation(facs.size() * 2);
return facinvs[this->val_];
}
MDCONST ModInt doublefac() const {
lint k = (this->val_ + 1) / 2;
return (this->val_ & 1) ? ModInt(k * 2).fac() / (ModInt(2).pow(k) * ModInt(k).fac())
: ModInt(k).fac() * ModInt(2).pow(k);
}
MDCONST ModInt nCr(const ModInt &r) const {
return (this->val_ < r.val_) ? 0 : this->fac() * (*this - r).facinv() * r.facinv();
}
MDCONST ModInt nPr(const ModInt &r) const {
return (this->val_ < r.val_) ? 0 : this->fac() * (*this - r).facinv();
}
ModInt sqrt() const {
if (val_ == 0) return 0;
if (md == 2) return val_;
if (pow((md - 1) / 2) != 1) return 0;
ModInt b = 1;
while (b.pow((md - 1) / 2) == 1) b += 1;
int e = 0, m = md - 1;
while (m % 2 == 0) m >>= 1, e++;
ModInt x = pow((m - 1) / 2), y = (*this) * x * x;
x *= (*this);
ModInt z = b.pow(m);
while (y != 1) {
int j = 0;
ModInt t = y;
while (t != 1) j++, t *= t;
z = z.pow(1LL << (e - j - 1));
x *= z, z *= z, y *= z;
e = j;
}
return ModInt(std::min(x.val_, md - x.val_));
}
};
template <int md> std::vector<ModInt<md>> ModInt<md>::facs = {1};
template <int md> std::vector<ModInt<md>> ModInt<md>::facinvs = {1};
template <int md> std::vector<ModInt<md>> ModInt<md>::invs = {0};
// using ModInt998244353 = ModInt<998244353>;
// using mint = ModInt<998244353>;
using mint = ModInt<1000000007>;
#line 5 "graph/test/enumerate_cliques.test.cpp"
using namespace std;
#define PROBLEM "https://judge.yosupo.jp/problem/enumerate_cliques"
int main() {
cin.tie(nullptr), ios::sync_with_stdio(false);
int N, M;
cin >> N >> M;
// using mint = ModInt998244353;
vector<mint> X(N,1);
// for (auto &x : X) cin >> x;
enumerate_cliques ec(N);
while (M--) {
int u, v;
cin >> u >> v;
u--;
v--;
ec.add_bi_edge(u, v);
}
mint ret = mint();
auto op = [&](const std::vector<int> &clique) -> void {
mint tmp = 1;
for (int x : clique) tmp *= X.at(x);
ret += tmp;
};
ec.run(op);
cout << ret << endl;
}
详细
Test #1:
score: 100
Accepted
time: 0ms
memory: 3864kb
input:
3 2 1 2 2 3
output:
5
result:
ok single line: '5'
Test #2:
score: 0
Accepted
time: 0ms
memory: 3640kb
input:
3 3 1 2 1 3 2 3
output:
7
result:
ok single line: '7'
Test #3:
score: 0
Accepted
time: 1ms
memory: 3688kb
input:
1000 100 446 789 167 547 254 777 777 185 33 446 777 847 185 877 757 167 72 383 847 446 254 478 959 185 757 446 847 959 959 167 757 847 747 757 446 167 989 757 547 777 33 747 33 254 254 843 33 547 446 980 877 205 185 72 980 959 33 205 877 757 33 847 478 843 757 478 167 877 72 789 877 959 980 478 167 ...
output:
1373
result:
ok single line: '1373'
Test #4:
score: -100
Wrong Answer
time: 103ms
memory: 3724kb
input:
1000 1000 770 105 219 498 686 498 343 534 15 591 919 588 149 588 298 915 551 523 710 116 105 637 523 991 343 476 145 420 604 588 254 120 551 421 476 298 900 710 915 343 445 421 986 867 445 588 219 356 919 105 584 875 991 604 776 919 588 254 919 421 356 348 105 551 15 113 919 15 356 523 343 155 770 9...
output:
3872127
result:
wrong answer 1st lines differ - expected: '6621319', found: '3872127'