1
0
Fork 0
You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

386 lines
9.7 KiB
C++

#include "Utilities.h"
#include <algorithm>
#include <cctype>
#include <functional>
#include <iomanip>
#include <ios>
#include <iostream>
#include <list>
#include <string>
using namespace std;
#ifndef __cpp_if_constexpr
#define constexpr
#endif // !__cpp_if_constexpr
template <typename T>
struct reverse_wrapper
{
T &iterable;
auto begin() { return std::rbegin(iterable); }
auto end() { return std::rend(iterable); }
};
template <typename T>
reverse_wrapper<T> reverse(T &&iterable) { return {iterable}; }
class ios_flags_guard
{
private:
ios *prev_stat, *curr_stat;
public:
ios_flags_guard(ios &cur)
{
prev_stat = new ios(nullptr);
curr_stat = &cur;
prev_stat->copyfmt(*curr_stat);
}
~ios_flags_guard()
{
curr_stat->copyfmt(*prev_stat);
delete prev_stat, curr_stat;
}
};
template <typename T>
struct _List_Node
{
using _p_List_Node = _List_Node *;
T val;
_p_List_Node pre, nxt;
};
template <typename T>
struct _List_Iterator
{
using iterator_category = bidirectional_iterator_tag;
using difference_type = ptrdiff_t;
using value_type = T;
using pointer = T *;
using reference = T &;
_List_Node<T> *pVal;
_List_Iterator(_List_Node<T> *p) : pVal(p) {}
reference operator*() const { return (*pVal).val; }
pointer operator->() const { return &(operator*()); }
_List_Iterator &operator++()
{
pVal = pVal->nxt;
return *this;
}
_List_Iterator operator++(int)
{
auto orig = *this;
pVal = pVal->nxt;
return orig;
}
_List_Iterator &operator--()
{
pVal = pVal->pre;
return *this;
}
_List_Iterator operator--(int)
{
auto orig = *this;
pVal = pVal->pre;
return orig;
}
bool operator==(const _List_Iterator &iter) const { return pVal == iter.pVal; }
bool operator!=(const _List_Iterator &iter) const { return pVal != iter.pVal; }
};
template <typename T>
class List
{
public:
using iterator = _List_Iterator<T>;
List()
{
sentinel = new _List_Node<T>();
sentinel->nxt = sentinel->pre = sentinel;
}
~List()
{
clear();
delete sentinel;
}
List &operator=(List &&rhs) noexcept
{
swap(sentinel, rhs.sentinel);
return *this;
}
List(List &&rhs) noexcept
{
sentinel = new _List_Node<T>();
sentinel->nxt = sentinel->pre = sentinel;
swap(sentinel, rhs.sentinel);
}
iterator begin() { return iterator(sentinel->nxt); }
iterator end() { return iterator(sentinel); }
iterator rbegin() { return iterator(sentinel->pre); }
iterator rend() { return iterator(sentinel); }
iterator insert(iterator pos, const T &v)
{
auto ptr = new _List_Node<T>();
ptr->val = v;
ptr->pre = pos.pVal->pre;
ptr->nxt = pos.pVal;
pos.pVal->pre->nxt = ptr;
pos.pVal->pre = ptr;
return ptr;
}
void erase(iterator pos)
{
pos.pVal->pre->nxt = pos.pVal->nxt;
pos.pVal->nxt->pre = pos.pVal->pre;
delete pos.pVal;
}
bool empty() const
{
return sentinel->nxt == sentinel;
}
void push_back(const T &v)
{
insert(end(), v);
}
void pop_back()
{
erase(rbegin());
}
void clear()
{
while (!empty()) erase(begin());
}
private:
_List_Node<T> *sentinel;
};
class BigInt
{
private:
List<int> lst;
void sanitize()
{
const int base = 10;
lst.push_back(0);
auto ite2 = lst.begin();
auto ite1 = ite2++;
for (; ite2 != lst.end(); ite1++, ite2++)
*ite2 += *ite1 / base, *ite1 %= base;
while (!lst.empty() && *lst.rbegin() == 0)
lst.pop_back();
}
public:
BigInt() {}
BigInt(BigInt &&rhs) noexcept : lst(move(rhs.lst)) {}
BigInt(const string &s)
{
if constexpr (0)
{
for (int st = s.length() - 3; st > -3; st -= 3)
{
int x = 0;
for (int i = max(st, 0); i < st + 3; i++)
x = x * 10 + s[i] - '0';
lst.push_back(x);
}
}
else
{
if (s.front() == '-')
{
for (auto c : reverse(s))
lst.push_back('0' - c);
lst.pop_back();
}
else
{
for (auto c : reverse(s))
lst.push_back(c - '0');
}
}
sanitize();
}
BigInt &operator=(BigInt &&rhs) noexcept
{
lst = move(rhs.lst);
return *this;
}
BigInt &operator=(const string &s)
{
lst.clear();
if (s.front() == '-')
{
for (auto c : reverse(s))
lst.push_back('0' - c);
lst.pop_back();
}
else
{
for (auto c : reverse(s))
lst.push_back(c - '0');
}
return *this;
}
BigInt operator+(BigInt &rhs)
{
BigInt ret;
for (auto ite1 = lst.begin(), ite2 = rhs.lst.begin();
ite1 != lst.end() || ite2 != rhs.lst.end();)
{
int v1 = ite1 != lst.end() ? *ite1++ : 0;
int v2 = ite2 != rhs.lst.end() ? *ite2++ : 0;
ret.lst.push_back(v1 + v2);
}
ret.sanitize();
return ret;
}
friend ostream &operator<<(ostream &out, BigInt &x)
{
if (x.lst.empty())
cout << 0;
else
{
if (*x.lst.rbegin() < 0) cout << "-";
for (auto ptr = x.lst.rbegin(); ptr != x.lst.rend(); ptr--)
cout << abs(*ptr);
// for (auto c : reverse(x.lst)) cout << abs(c);
}
return out;
}
void insert(int p, int v)
{
auto ite = lst.begin();
if (*ite < 0) v = -v;
advance(ite, p);
lst.insert(ite, v);
sanitize();
}
void remove(int p)
{
auto ite = lst.begin();
advance(ite, p);
lst.erase(ite);
sanitize();
}
};
int rep = 200, caps[120], rndres[201];
char buf[1200001];
char *filename =
#ifdef _DEBUG
"debugres.txt"
#else
"releaseres.txt"
#endif // _DEBUG
;
int main()
{
auto fp = fopen(filename, "w");
for (int i = 0; i < 120; i++) caps[i] = (i + 1) * 10000;
if constexpr (1)
{
Timer timer;
MemoryMonitor mm;
Random rnd;
vector<string> ss(sqrt(rep) + 1);
for (int sz : caps)
{
for (auto &s : ss)
{
for (int i = 0; i < sz; i++) buf[i] = rnd.next('0', '9' + 1);
buf[sz] = 0;
s = buf;
}
vector<BigInt> is(ss.size());
BigInt tmp_;
for (int i = 0; i < ss.size(); i++) is[i] = ss[i];
for (int i = 200; i; i--) rndres[i] = rnd.next(0, sz / 2);
// add test
timer.start();
mm.reset();
([&] {
int cnt = rep;
for (auto &x : is)
for (auto &y : is)
{
tmp_ = x + y;
if (--cnt == 0) return;
}
})();
timer.stop();
mm.save();
printf("len %d add %d times time %.6lf ms, mem %lld bytes.\n",
sz, rep, timer.diff_in_ms(), mm.max_usage());
fprintf(fp, "add,%.9lf,%lld\n", timer.diff_in_ms() / 1000, mm.max_usage());
// del test
timer.start();
mm.reset();
([&] {
int cnt = rep;
for (;;)
for (auto &x : is)
{
x.remove(rndres[cnt]);
if (--cnt == 0) return;
}
})();
timer.stop();
mm.save();
printf("len %d del %d times time %.6lf ms, mem %lld bytes.\n",
sz, rep, timer.diff_in_ms(), mm.max_usage());
fprintf(fp, "del,%.9lf,%lld\n", timer.diff_in_ms() / 1000, mm.max_usage());
// add test
timer.start();
mm.reset();
([&] {
int cnt = rep;
for (;;)
for (auto &x : is)
{
x.insert(rndres[cnt], 0);
if (--cnt == 0) return;
}
})();
timer.stop();
mm.save();
printf("len %d ins %d times time %.6lf ms, mem %lld bytes.\n",
sz, rep, timer.diff_in_ms(), mm.max_usage());
fprintf(fp, "ins,%.9lf,%lld\n", timer.diff_in_ms() / 1000, mm.max_usage());
}
fclose(fp);
system("pause");
return 0;
}
const auto filter = [](char c) { return !isdigit(c) && c != '-'; };
const auto string_sanitize = [&filter](string &s) -> string & {
s.erase(remove_if(s.begin(), s.end(), filter), s.end());
return s;
};
int T, op;
string s1, s2;
cin >> T;
while (T--)
{
cin >> op;
if (op == 1)
{
cin >> s1 >> s2;
BigInt n1(string_sanitize(s1)), n2(string_sanitize(s2));
cout << n1 + n2 << endl;
}
if (op == 2)
{
int x, y;
cin >> s1 >> x >> y;
BigInt n1(string_sanitize(s1));
n1.insert(x, y);
cout << n1 << endl;
}
if (op == 3)
{
int x;
cin >> s1 >> x;
BigInt n1(string_sanitize(s1));
n1.remove(x);
cout << n1 << endl;
}
}
return 0;
}