QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#336753 | #8285. Shell Sort | ucup-team1191# | TL | 1295ms | 18100kb | C++20 | 9.8kb | 2024-02-24 20:50:21 | 2024-02-24 20:50:22 |
Judging History
answer
#include <bits/stdc++.h>
#define fr first
#define sc second
#define all(a) (a).begin(), (a).end()
#define unique(a) a.resize(unique(a.begin(), a.end()) - a.begin())
using namespace std;
#ifdef ONPC
mt19937 rnd(223);
#else
mt19937 rnd(chrono::high_resolution_clock::now()
.time_since_epoch().count());
#endif
#define TIME (clock() * 1.0 / CLOCKS_PER_SEC)
using ll = long long;
using ld = double;
const int maxn = 1e5 + 100, inf = 1e9 + 100;
// если модуль подается на вход, убрать все <> и раскомментировать нужные строки
using uint = unsigned int;
using ull = unsigned long long;
template <uint MD> struct ModInt {
using M = ModInt;
// static int MD;
uint v;
ModInt(ll _v = 0) { set_v(uint(_v % MD + MD)); }
M& set_v(uint _v) {
v = (_v < MD) ? _v : _v - MD;
return *this;
}
explicit operator bool() const { return v != 0; }
M operator-() const { return M() - *this; }
M operator+(const M& r) const { return M().set_v(v + r.v); }
M operator-(const M& r) const { return M().set_v(v + MD - r.v); }
M operator*(const M& r) const { return M().set_v(uint((ull)v * r.v % MD)); }
M operator/(const M& r) const { return *this * r.inv(); }
M& operator+=(const M& r) { return *this = *this + r; }
M& operator-=(const M& r) { return *this = *this - r; }
M& operator*=(const M& r) { return *this = *this * r; }
M& operator/=(const M& r) { return *this = *this / r; }
bool operator==(const M& r) const { return v == r.v; }
bool operator!=(const M& r) const { return v != r.v; }
M inv() const;
friend istream& operator>>(istream& is, M& r) { ll x; is >> x; r = M(x); return is; }
friend ostream& operator<<(ostream& os, const M& r) { return os << r.v; }
};
template<uint MD>
ModInt<MD> pow(ModInt<MD> x, ll n) {
ModInt<MD> r = 1;
while (n) {
if (n & 1) r *= x;
x *= x;
n >>= 1;
}
return r;
}
template<uint MD>
ModInt<MD> ModInt<MD>::inv() const { return pow(*this, MD - 2); }
// or copy egcd and {return egcd(MD, v, 1).second;}
// if MD is from input
// this line is necessary, read later as you wish
// int ModInt::MD;
using Mint = ModInt<1'000'000'007>;
// using Mint = double;
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
int cur_cnt;
gp_hash_table<int, int> masks;
vector<tuple<int, int, int>> in[32];
vector<int> p;
int calc(const vector<int>& d) {
int ans = 0;
for (int t : d) {
for (int i = t; i < (int)p.size(); ++i) {
int j = i;
while (j >= t && p[j - t] > p[j]) {
if (p[j] == 1) {
++ans;
}
swap(p[j - t], p[j]);
j -= t;
}
}
}
return ans;
}
void gen(int n, int mask, int t, const vector<int>& d) {
int mid = cur_cnt++;
masks[mask] = mid;
if (mask == 0) {
return;
}
for (int i = 0; i < n; i++) {
if (((mask >> i) & 1) == 1 && (i < t || ((mask >> (i - t)) & 1) == 0)) {
int new_mask = mask ^ (1 << i);
for (int x = 0; x < n; x++) {
if (x == i) {
p[x] = 1;
} else {
if ((mask >> x) & 1) {
p[x] = 2;
} else {
p[x] = 0;
}
}
}
int w = calc(d);
if (masks.find(new_mask) == masks.end()) {
gen(n, new_mask, t, d);
}
in[__builtin_popcount(mask)].emplace_back(mid, masks[new_mask], w);
}
}
}
pair<int, Mint> fast(int n, const vector<int>& d) {
if (d.size() == 1) {
return {n * (n - 1) / 2, Mint(1)};
}
p.resize(n);
masks.clear();
//masks.reserve(2e6);
for (int i = 0; i <= n; i++) {
in[i].clear();
}
cur_cnt = 0;
int add = 0;
for (int ost = 0; ost < d[0]; ost++) {
int cnt = (n - ost + d[0] - 1) / d[0];
add += cnt * (cnt - 1) / 2;
}
gen(n, (1 << n) - 1, d[0], d);
vector<pair<int, Mint>> dp(masks.size(), make_pair(-1, 0));
dp[masks[0]] = make_pair(add, 1);
for (int sz = 1; sz <= n; sz++) {
for (auto [from, to, w] : in[sz]) {
auto pr = dp[to];
pr.first += w;
if (dp[from].first < pr.first) {
dp[from].first = pr.first;
dp[from].second = 0;
}
if (dp[from].first == pr.first) {
dp[from].second += pr.second;
}
}
}
return dp[masks[(1 << n) - 1]];
}
int calc(vector<int> p, const vector<int>& d) {
int ans = 0;
for (int t : d) {
for (int i = t; i < (int)p.size(); ++i) {
int j = i;
while (j >= t && p[j - t] > p[j]) {
swap(p[j - t], p[j]);
++ans;
j -= t;
}
}
}
return ans;
}
auto solve(int n, const vector<int>& d) {
mt19937 rnd(239);
int best = -1;
set<vector<int>> best_p;
int last_it = -1;
vector<pair<int, int>> swaps;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < i; ++j) {
swaps.emplace_back(j, i);
}
}
for (int random_it = 0; random_it < last_it * 2 + 1000; random_it++) {
vector<int> p(n);
iota(p.begin(), p.end(), 0);
shuffle(p.begin(), p.end(), rnd);
int cur = calc(p, d);
shuffle(all(swaps), rnd);
int i_swaps = 0;
int unchanged = 0;
for (int inner_it = 0; inner_it < 10000 && unchanged <= swaps.size() * 2; inner_it++) {
auto [i, j] = swaps[i_swaps];
++i_swaps;
if (i_swaps == swaps.size()) {
shuffle(all(swaps), rnd);
i_swaps = 0;
}
swap(p[i], p[j]);
int new_val = calc(p, d);
unchanged++;
if (new_val >= cur) {
if (new_val > cur) {
unchanged--;
}
cur = new_val;
if (best < cur) {
best_p.clear();
best = cur;
}
if (best == cur) {
if (best_p.insert(p).second) {
last_it = random_it;
}
}
} else {
swap(p[i], p[j]);
}
}
}
return make_tuple(best, (int)best_p.size(), last_it);
}
vector<int> opt;
vector<vector<int>> opts;
int n;
void gen() {
opts.emplace_back(opt.rbegin(), opt.rend());
for (int k = opt.back() + 1; k < n && k <= 10; ++k) {
opt.push_back(k);
gen();
opt.pop_back();
}
}
void solve() {
//*
cin >> n;
int m;
cin >> m;
vector<int> d(m);
for (int i = 0; i < m; i++) {
cin >> d[i];
}
auto [v1, v2] = fast(n, d);
cout << v1 << " " << v2 << "\n";
return;
//*/
n = 10;
opt = {1};
gen();
vector<int> p(n);
vector<int> v(n);
int it = 0;
for (const auto& d : opts) {
++it;
cerr << it << "/" << opts.size() << endl;
// iota(all(p), 1);
// int max_ans = -1;
// int cnt = 0;
// vector<int> sample;
// vector<set<vector<int>>> hists(d.size());
// do {
// for (int i = 0; i < n; ++i) {
// v[i] = p[i];
// }
// int cur = 0;
// int iit = 0;
// vector<vector<int>> hist;
// for (int t : d) {
// hist.push_back(v);
// for (int i = t; i < n; ++i) {
// int j = i;
// while (j >= t && v[j - t] > v[j]) {
// swap(v[j - t], v[j]);
// ++cur;
// j -= t;
// }
// }
// ++iit;
// }
// if (cur > max_ans) {
// for (auto& v : hists)
// v.clear();
// max_ans = cur;
// sample = p;
// cnt = 0;
// }
// if (cur == max_ans) {
// for (int i = 0; i < hists.size(); ++i) {
// hists[i].insert(hist[i]);
// }
// ++cnt;
// }
// } while (next_permutation(all(p)));
// cout << "ans=" << max_ans << " \tcnt=" << cnt;
// cout << " \tpath =";
// for (auto& v : hists)
// cout << ' ' << v.size();
// cout << ' ' << 1;
cout << " \tfor d =";
for (int i : d)
cout << ' ' << i;
// cout << " \tsample =";
// for (int i : sample)
// cout << ' ' << i;
cout << "| ";
auto [fast_ans, fast_cnt, fast_last_it] = solve(n, d);
// if (make_pair(fast_ans, fast_cnt) != make_pair(max_ans, cnt)) {
// cout << " HUY";
// }
auto [best_ans, best_cnt] = fast(n, d);
assert(best_ans == fast_ans && best_cnt == fast_cnt);
cout << " " << fast_ans << " " << fast_cnt << ' ' << fast_last_it;
cout << "\n";
cout << best_ans << " " << best_cnt << "\n";
if (fast_last_it > 5000)
cout << " !!!!!!!!!!!!!!!!!!!";
cout << '\n';
}
}
int main() {
#ifdef ONPC
freopen("../a.in", "r", stdin);
freopen("../a.out", "w", stdout);
#endif
ios::sync_with_stdio(0);
cin.tie(0);
cout << fixed;
cout.precision(20);
solve();
cerr << "\n\nConsumed " << TIME << endl;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3976kb
input:
2 2 2 1
output:
1 1
result:
ok 2 number(s): "1 1"
Test #2:
score: 0
Accepted
time: 0ms
memory: 3920kb
input:
5 4 5 4 2 1
output:
6 4
result:
ok 2 number(s): "6 4"
Test #3:
score: 0
Accepted
time: 1ms
memory: 3888kb
input:
8 4 6 3 2 1
output:
15 4
result:
ok 2 number(s): "15 4"
Test #4:
score: 0
Accepted
time: 1ms
memory: 4164kb
input:
8 6 8 7 5 4 2 1
output:
14 2
result:
ok 2 number(s): "14 2"
Test #5:
score: 0
Accepted
time: 1ms
memory: 4084kb
input:
8 3 8 7 1
output:
22 7
result:
ok 2 number(s): "22 7"
Test #6:
score: 0
Accepted
time: 0ms
memory: 3836kb
input:
8 1 1
output:
28 1
result:
ok 2 number(s): "28 1"
Test #7:
score: 0
Accepted
time: 2ms
memory: 4112kb
input:
16 2 6 1
output:
77 15
result:
ok 2 number(s): "77 15"
Test #8:
score: 0
Accepted
time: 13ms
memory: 5168kb
input:
16 8 10 9 8 7 6 5 4 1
output:
57 5
result:
ok 2 number(s): "57 5"
Test #9:
score: 0
Accepted
time: 21ms
memory: 5304kb
input:
16 10 10 9 8 7 6 5 4 3 2 1
output:
57 3
result:
ok 2 number(s): "57 3"
Test #10:
score: 0
Accepted
time: 14ms
memory: 5220kb
input:
16 7 10 9 8 6 5 4 1
output:
49 1
result:
ok 2 number(s): "49 1"
Test #11:
score: 0
Accepted
time: 5ms
memory: 4136kb
input:
16 4 7 6 2 1
output:
52 9
result:
ok 2 number(s): "52 9"
Test #12:
score: 0
Accepted
time: 6ms
memory: 4200kb
input:
22 3 5 3 1
output:
100 1
result:
ok 2 number(s): "100 1"
Test #13:
score: 0
Accepted
time: 0ms
memory: 4008kb
input:
22 1 1
output:
231 1
result:
ok 2 number(s): "231 1"
Test #14:
score: 0
Accepted
time: 908ms
memory: 18048kb
input:
22 4 10 8 3 1
output:
97 4
result:
ok 2 number(s): "97 4"
Test #15:
score: 0
Accepted
time: 1248ms
memory: 18064kb
input:
22 5 10 7 6 3 1
output:
92 70
result:
ok 2 number(s): "92 70"
Test #16:
score: 0
Accepted
time: 934ms
memory: 18100kb
input:
22 6 10 9 8 7 3 1
output:
97 1
result:
ok 2 number(s): "97 1"
Test #17:
score: 0
Accepted
time: 1295ms
memory: 18092kb
input:
22 10 10 9 8 7 6 5 4 3 2 1
output:
109 1
result:
ok 2 number(s): "109 1"
Test #18:
score: 0
Accepted
time: 5ms
memory: 4112kb
input:
14 2 10 1
output:
61 210
result:
ok 2 number(s): "61 210"
Test #19:
score: 0
Accepted
time: 1ms
memory: 3992kb
input:
18 2 2 1
output:
117 1
result:
ok 2 number(s): "117 1"
Test #20:
score: -100
Time Limit Exceeded
input:
30 2 9 1