QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#91235 | #6126. Sequence and Sequence | Golovanov399 | AC ✓ | 7582ms | 261916kb | C++20 | 16.8kb | 2023-03-27 20:20:27 | 2023-03-27 20:20:29 |
Judging History
answer
#include <bits/stdc++.h>
#include <algorithm>
#include <cctype>
#include <compare>
#include <cstdint>
#include <string>
#include <vector>
#include <iomanip>
#include <iostream>
#include <sstream>
#include <stdexcept>
#include <type_traits>
using li = long long;
using LI = __int128_t;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
template <typename> struct next_size;
template <typename T> using next_size_t = typename next_size<T>::type;
template <typename T> struct tag { using type = T; };
template <> struct next_size<int8_t> : tag<int16_t> {};
template <> struct next_size<int16_t> : tag<int32_t> {};
template <> struct next_size<int32_t> : tag<int64_t> {};
template <> struct next_size<int64_t> : tag<__int128_t> {};
template <> struct next_size<long long> : tag<__int128_t> {};
ld eps = 1e-8;
void set_eps(ld new_eps) {
eps = new_eps;
}
template <typename T>
std::enable_if_t<std::is_integral_v<T>, int> sign(T x) {
return x < 0 ? -1 : x > 0;
}
template <typename T>
std::enable_if_t<std::is_floating_point_v<T>, int> sign(T x) {
return x < -eps ? -1 : x > eps;
}
using std::vector, std::strong_ordering;
struct BigInteger {
using u32 = uint32_t;
using u64 = uint64_t;
using i64 = int64_t;
static constexpr u32 BASE = 1'000'000'000;
static constexpr int BASE_LEN = [](u32 base) { int res = 0; while (base > 1) { base /= 10; ++res; } return res; }(BASE);
vector<u32> digits;
bool neg;
BigInteger(long long x = 0): neg(false) {
if (x < 0) {
neg = true;
x = -x;
}
while (x) {
digits.push_back(x % BASE);
x /= BASE;
}
}
BigInteger(const std::string& s) {
neg = false;
digits = {};
int i = (int)s.length() - 1;
while (i >= 0 && std::isdigit(s[i])) {
int j = i;
while (j >= 0 && j > i - BASE_LEN && std::isdigit(s[j])) {
--j;
}
digits.push_back(std::stoi(s.substr(j + 1, i - j)));
i = j;
}
if (i > 0 || (i == 0 && s[i] != '-' && s[i] != '+')) {
throw std::runtime_error("invalid biginteger");
} else if (i == 0 && s[i] == '-') {
neg = true;
}
shrink();
}
BigInteger from_int128(__int128_t x) {
BigInteger res;
if (x < 0) {
res.neg = true;
x = -x;
}
while (x) {
res.digits.push_back(x % BASE);
x /= BASE;
}
return res;
}
static BigInteger from_digits(const vector<u32>& dgs, bool neg = false) {
BigInteger res;
res.digits = dgs;
res.neg = neg;
return res;
}
void shrink() {
while (!digits.empty() && !digits.back()) {
digits.pop_back();
}
if (digits.empty()) {
neg = false;
}
}
int _cmp(const BigInteger& ot) const {
if (digits.size() != ot.digits.size()) {
return sign((int)digits.size() - (int)ot.digits.size());
}
for (int i = (int)digits.size() - 1; i >= 0; --i) {
if (digits[i] != ot.digits[i]) {
return sign((int)digits[i] - (int)ot.digits[i]);
}
}
return 0;
}
void _add(const vector<u32>& dgs) {
u32 carry = 0;
if (dgs.size() > digits.size()) {
digits.resize(dgs.size());
}
for (int i = 0; i < (int)digits.size() || i < (int)dgs.size(); ++i) {
if (i < (int)digits.size()) {
carry += digits[i];
}
if (i < (int)dgs.size()) {
carry += dgs[i];
}
digits[i] = carry % BASE;
carry /= BASE;
}
if (carry) {
digits.push_back(carry);
}
}
void _sub(const vector<u32>& dgs) {
u32 carry = 0;
for (int i = 0; i < (int)digits.size(); ++i) {
if (i < (int)dgs.size()) {
carry += dgs[i];
}
if (digits[i] >= carry) {
digits[i] -= carry;
carry = 0;
} else {
digits[i] += BASE;
digits[i] -= carry;
carry = 1;
}
}
shrink();
}
static vector<u32> _mul(const vector<u32>& a, const vector<u32>& b) {
if (a.empty() || b.empty()) {
return {};
}
vector<u32> res(a.size() + b.size() - 1);
u64 carry = 0;
for (int i = 0; i < (int)a.size() + (int)b.size() - 1; ++i) {
res[i] = carry % BASE;
carry /= BASE;
int from = std::max(0, i - (int)b.size() + 1);
int to = std::min((int)a.size() - 1, i);
for (int j = from; j <= to; ++j) {
u64 tmp = (u64)a[j] * b[i - j];
carry += tmp / BASE;
res[i] += tmp % BASE;
if (res[i] >= BASE) {
res[i] -= BASE;
carry += 1;
}
}
}
while (carry > 0) {
res.push_back(carry % BASE);
carry /= BASE;
}
return res;
}
static int _len(const vector<u32>& dgs) {
if (dgs.empty()) {
return 0;
} else {
return ((int)dgs.size() - 1) * BASE_LEN + std::to_string(dgs.back()).length();
}
}
static vector<u32> _div(vector<u32> a, const vector<u32>& b) {
vector<u32> res;
u64 cur = 0;
for (int i = (int)a.size() - 1; i >= (int)b.size() - 1; --i) {
cur *= BASE;
cur += a[i];
u32 le = cur / (b.back() + 1);
u32 ri = cur / b.back() + 1;
while (ri > le + 1) {
u32 k = le + (ri - le) / 2;
u64 can = cur;
bool ok = true;
for (int j = 0; j < (int)b.size(); ++j) {
if (j) {
can = can * BASE + a[i - j];
}
if (can < (u64)b[(int)b.size() - 1 - j] * k) {
ok = false;
break;
}
can -= (u64)b[(int)b.size() - 1 - j] * k;
if (can >= k) {
break;
}
}
(ok ? le : ri) = k;
}
u32 k = le;
res.push_back(k);
u64 carry = 0;
for (int j = (int)b.size() - 1; j > 0; --j) {
carry += (u64)b[(int)b.size() - 1 - j] * k;
if (carry % BASE <= a[i - j]) {
a[i - j] -= carry % BASE;
} else {
a[i - j] += BASE;
a[i - j] -= carry % BASE;
carry += BASE;
}
carry /= BASE;
}
carry += (u64)b.back() * k;
cur -= carry;
}
reverse(res.begin(), res.end());
return res;
}
BigInteger& operator +=(const BigInteger& ot) {
if (neg == ot.neg) {
_add(ot.digits);
} else if (_cmp(ot) < 0) {
neg = ot.neg;
auto d = digits;
digits = ot.digits;
_sub(d);
} else {
_sub(ot.digits);
}
return *this;
}
BigInteger& operator -=(const BigInteger& ot) {
if (neg == !ot.neg) {
_add(ot.digits);
} else if (_cmp(ot) < 0) {
neg = !ot.neg;
auto d = digits;
digits = ot.digits;
_sub(d);
} else {
_sub(ot.digits);
}
return *this;
}
BigInteger operator +(const BigInteger& ot) const {
BigInteger res = *this;
res += ot;
return res;
}
BigInteger operator -(const BigInteger& ot) const {
BigInteger res = *this;
res -= ot;
return res;
}
BigInteger operator -() const {
auto res = *this;
if (!digits.empty()) {
res.neg ^= 1;
}
return res;
}
BigInteger& operator *=(const BigInteger& ot) {
if (digits.empty() || ot.digits.empty()) {
digits = {};
neg = false;
return *this;
}
digits = _mul(digits, ot.digits);
neg ^= ot.neg;
return *this;
}
BigInteger operator *(const BigInteger& ot) const {
if (digits.empty() || ot.digits.empty()) {
return from_digits({});
}
return from_digits(_mul(digits, ot.digits), neg ^ ot.neg);
}
BigInteger& operator /=(i64 x) { // negative numbers are divided as in C++
if (x == 0) {
throw std::domain_error("division by zero");
}
if (x < 0) {
neg ^= 1;
x = -x;
}
u64 carry = 0;
for (int i = (int)digits.size() - 1; i >= 0; --i) {
carry *= BASE;
carry += digits[i];
digits[i] = carry / x;
carry %= x;
}
shrink();
return *this;
}
BigInteger operator /(i64 x) const {
auto res = *this;
res /= x;
return res;
}
i64 operator %(i64 x) const {
if (x == 0) {
throw std::domain_error("division by zero");
}
bool flip = neg;
if (x < 0) {
flip ^= 1;
x = -x;
}
u64 carry = 0;
for (int i = (int)digits.size() - 1; i >= 0; --i) {
carry *= BASE;
carry += digits[i];
carry %= x;
}
return (i64)carry * (flip ? -1 : 1);
}
BigInteger& operator %=(i64 x) {
*this = *this % x;
return *this;
}
BigInteger& operator /=(const BigInteger& ot) {
if (ot.digits.empty()) {
throw std::domain_error("division by zero");
}
if (digits.empty()) {
return *this;
}
neg ^= ot.neg;
digits = _div(digits, ot.digits);
shrink();
return *this;
}
BigInteger operator /(const BigInteger& ot) const {
auto res = *this;
res /= ot;
return res;
}
strong_ordering operator <=>(const BigInteger& ot) const {
if (neg != ot.neg) {
return neg ? strong_ordering::less : strong_ordering::greater;
} else {
int s = _cmp(ot);
if (neg) {
s = -s;
}
return s < 0 ? strong_ordering::less : s > 0 ? strong_ordering::greater : strong_ordering::equal;
}
}
bool operator ==(const BigInteger& ot) const {
return neg == ot.neg && digits == ot.digits;
}
BigInteger pow(u32 x) const {
if (!x) {
return 1;
}
BigInteger res = 1;
for (int i = 31 - __builtin_clz(x); i >= 0; --i) {
res *= res;
if ((x >> i) & 1) {
res *= *this;
}
}
return res;
}
std::string to_string() const {
std::string s;
std::ostringstream ss(s);
ss << *this;
return s;
}
void drop_digits(int cnt) {
if (!cnt) {
return;
}
int blocks = cnt / BASE_LEN;
if (blocks >= (int)digits.size()) {
digits = {};
shrink();
return;
}
digits.erase(digits.begin(), digits.begin() + blocks);
int rem = cnt - blocks * BASE_LEN;
if (rem) {
const u32 tp = [](int deg) { u32 res = 1; while (deg--) { res *= 10; } return res; }(rem);
for (int i = 0; i + 1 < (int)digits.size(); ++i) {
digits[i] = digits[i] / tp + (digits[i + 1] % tp) * (BASE / tp);
}
digits.back() /= tp;
shrink();
}
}
void add_zeroes(int cnt) {
if (digits.empty()) {
return;
}
int blocks = (cnt + BASE_LEN - 1) / BASE_LEN;
digits.resize(digits.size() + blocks);
std::copy(digits.begin(), digits.begin() + (int)digits.size() - blocks, digits.begin() + blocks);
std::fill(digits.begin(), digits.begin() + blocks, 0);
drop_digits(blocks * BASE_LEN - cnt);
}
void leave_digits(int cnt) {
int blocks = (cnt + BASE_LEN - 1) / BASE_LEN;
if (blocks > (int)digits.size()) {
return;
}
digits.resize(blocks);
if (cnt != blocks * BASE_LEN) {
int rem = cnt - (blocks - 1) * BASE_LEN;
const u32 tp = [](int deg) { u32 res = 1; while (deg--) { res *= 10; } return res; }(rem);
digits.back() %= tp;
}
shrink();
}
int length() const {
return _len(digits);
}
int to_int() const {
int res = 0;
for (auto x : digits) {
res = res * BASE + x;
}
if (neg) {
res = -res;
}
return res;
}
long long to_long() const {
long long res = 0;
for (auto x : digits) {
res = res * BASE + x;
}
if (neg) {
res = -res;
}
return res;
}
friend std::ostream& operator <<(std::ostream& ostr, const BigInteger& num) {
if (num.neg) {
ostr << "-";
}
for (int i = (int)num.digits.size() - 1; i >= 0; --i) {
if (i < (int)num.digits.size() - 1) {
ostr << std::setfill('0') << std::setw(BASE_LEN);
}
ostr << num.digits[i];
}
if (num.digits.empty()) {
ostr << "0";
}
return ostr;
}
friend std::istream& operator >>(std::istream& istr, BigInteger& num) {
std::string s;
istr >> s;
num = BigInteger(s);
return istr;
}
};
#define all(x) (x).begin(), (x).end()
using namespace std;
int nxt() {
int x;
cin >> x;
return x;
}
struct Fraction {
BigInteger num;
long long denom;
Fraction(int x = 0): num(x), denom(1) {}
Fraction(long long x): num(x), denom(1) {}
Fraction(const BigInteger& n): num(n), denom(1) {}
Fraction(int x, int y): num(x), denom(y) {
cancel_out();
}
void cancel_out() {
auto g = num % denom;
g = gcd(g, denom);
if (g > 1) {
denom /= g;
num /= g;
}
}
Fraction& operator +=(const Fraction& ot) {
num = num * ot.denom + ot.num * denom;
denom *= ot.denom;
cancel_out();
return *this;
}
Fraction& operator -=(const Fraction& ot) {
num = num * ot.denom - ot.num * denom;
denom *= ot.denom;
cancel_out();
return *this;
}
Fraction& operator *=(const Fraction& ot) {
num *= ot.num;
denom *= ot.denom;
cancel_out();
return *this;
}
Fraction& operator /=(long long x) {
denom *= x;
cancel_out();
return *this;
}
friend Fraction operator +(Fraction a, const Fraction& b) {
return a += b;
}
friend Fraction operator -(Fraction a, const Fraction& b) {
return a -= b;
}
friend Fraction operator *(Fraction a, const Fraction& b) {
return a *= b;
}
Fraction operator -() const {
auto res = *this;
res.num *= -1;
return res;
}
friend ostream& operator <<(ostream& ostr, const Fraction& f) {
ostr << f.num;
if (f.denom > 1) {
ostr << "/" << f.denom;
}
return ostr;
}
};
using Poly = vector<Fraction>;
Poly add(const Poly& a, const Poly& b) {
Poly res(max(a.size(), b.size()));
for (int i = 0; i < (int)a.size(); ++i) {
res[i] += a[i];
}
for (int i = 0; i < (int)b.size(); ++i) {
res[i] += b[i];
}
return res;
}
Poly sub(const Poly& a, const Poly& b) {
Poly res(max(a.size(), b.size()));
for (int i = 0; i < (int)a.size(); ++i) {
res[i] += a[i];
}
for (int i = 0; i < (int)b.size(); ++i) {
res[i] -= b[i];
}
return res;
}
Poly mult(const Poly& a, const Poly& b) {
Poly res((int)a.size() + b.size() - 1);
for (int i = 0; i < (int)a.size(); ++i) {
for (int j = 0; j < (int)b.size(); ++j) {
res[i + j] += a[i] * b[j];
}
}
return res;
}
Poly subst(const Poly& p, const Poly& q) {
Poly res;
Poly cur = {1};
for (auto c : p) {
auto tmp = cur;
for (auto& x : tmp) {
x *= c;
}
res = add(res, tmp);
cur = mult(cur, q);
}
return res;
}
Fraction apply_poly(const Poly& p, Fraction x) {
Fraction res = 0;
for (int i = (int)p.size() - 1; i >= 0; --i) {
res = res * x + p[i];
}
return res;
}
Poly norm_to_bin(Poly p) {
Poly res(p.size());
vector<Poly> bins = {{1}};
for (int i = 0; i < (int)p.size() - 1; ++i) {
auto q = mult(bins.back(), {i, 1});
bins.push_back(q);
}
for (int i = (int)p.size() - 1; i >= 0; --i) {
auto c = p[i];
res[i] = c;
auto tmp = bins[i];
for (auto& x : tmp) {
x *= c;
}
p = sub(p, tmp);
}
return res;
}
Poly lift(Poly p) {
p.insert(p.begin(), 0);
for (int i = 1; i < (int)p.size(); ++i) {
p[i] /= i;
}
return p;
}
Poly bin_to_norm(const Poly& p) {
Poly res;
Poly q = {1};
for (int i = 0; i < (int)p.size(); ++i) {
auto tmp = q;
for (auto& x : tmp) {
x *= p[i];
}
res = add(res, tmp);
q = mult(q, {i, 1});
}
return res;
}
Poly _poly_to_sum(const Poly& p) {
return bin_to_norm(lift(norm_to_bin(p)));
}
const int N = 184'000;
const int D = 17;
vector<Poly> pss = []() {
vector<Poly> res(D);
for (int i = 0; i < D; ++i) {
res[i].resize(i + 1);
res[i].back() = 1;
res[i] = _poly_to_sum(res[i]);
}
return res;
}();
Poly poly_to_sum(const Poly& p) {
Poly res;
for (int i = 0; i < (int)p.size(); ++i) {
auto tmp = pss[i];
for (auto& x : tmp) {
x *= p[i];
}
res = add(res, tmp);
}
return res;
}
Fraction sumpoly(const Poly& p, const Fraction& x) {
return apply_poly(poly_to_sum(p), x);
}
BigInteger isqrt(BigInteger n) {
if (n <= 1) {
return n;
}
BigInteger x = n / 2;
BigInteger y = (x + n / x) / 2;
while (y < x) {
x = y;
y = (x + n / x) / 2;
}
return x;
}
BigInteger S(BigInteger n) {
return (n + 1) * (n + 2) / 2 - 1;
}
BigInteger P(BigInteger n) {
auto k = (isqrt(n * 8 + 9) - 3) / 2;
while (S(k) < n) {
k += 1;
}
return k;
}
Fraction Q[N];
Fraction prefQ[D][N];
Fraction find_Q(BigInteger n);
Fraction f(BigInteger n, Poly p) {
if (n < N) {
auto nn = n.to_int();
Fraction ans = 0;
for (int i = 0; i < (int)p.size(); ++i) {
ans += prefQ[i][nn] * p[i];
}
return ans;
}
auto mx = P(n);
auto fr = S(mx - 1) + 1;
p = poly_to_sum(p);
auto q = subst(p, {-1, 1});
for (auto& x : q) {
x = -x;
}
q[0] += apply_poly(p, n);
q = poly_to_sum(q);
auto ans = find_Q(mx) * (apply_poly(q, n) - apply_poly(q, fr - 1));
q = sub(subst(q, {0, Fraction(3, 2), Fraction(1, 2)}), subst(q, {-1, Fraction(1, 2), Fraction(1, 2)}));
ans += f(mx - 1, q);
return ans;
}
Fraction find_Q(BigInteger n) {
if (n < N) {
return Q[n.to_int()];
}
auto mx = P(n);
return f(mx, {1, 1}) - find_Q(mx) * (S(mx) - n);
}
void solve() {
BigInteger n;
cin >> n;
cout << find_Q(n) << "\n";
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
Q[1] = 1;
for (int i = 0; i < D; ++i) {
prefQ[i][1] = 1;
}
for (int i = 2; i < N; ++i) {
Q[i] = Q[i - 1] + Q[P(i).to_int()];
auto cur = Q[i];
for (int j = 0; j < D; ++j) {
prefQ[j][i] = prefQ[j][i - 1] + cur;
cur *= i;
}
}
int t = nxt();
while (t--) {
solve();
}
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 2372ms
memory: 261892kb
input:
4 10 100 1000 987654321123456789
output:
30 2522 244274 235139898689017607381017686096176798
result:
ok 4 lines
Test #2:
score: 0
Accepted
time: 3115ms
memory: 261840kb
input:
10000 613939207402503646 408978283345333197 976677512231308716 629053280913850466 148712339 236220313279945487 590396556995977994 9226 215693877607285701 649702683896705 343173887453826567 847003949499596615 867133040287550291 159928123569892354 864534948175618654 209739383170746721 4295456752378791...
output:
91030728117067063595428375419346402 40469246710473908695676971059074376 229951682342450470520349294486964970 95558039501640054006660579352994194 5418340556433412 13536357243714243974772906966693552 84197207203086091733385317631619504 20934656 11291075621624104092841708040651034 104019777231815308683...
result:
ok 10000 lines
Test #3:
score: 0
Accepted
time: 2792ms
memory: 261852kb
input:
1000 6403632579734162001008235137760132245297 1307698664787972023762442022139627469666 668870338048562416595095770565441759482 5092270 8806864498496723812760785099973409980711 2178464116010775202899984038946879469187 204381824371 8638495456004772442511643693521120926431 45954412333082528168092594892...
output:
9822905445826021159291522774438593145331066315784567505849706373529921001845336 409552844852728078841401625660602682494169687360338453221088647649526339235330 107160056181509722327918304399871120167096186888511567354513496578559803370274 6354453295964 185817323129718525790559571287806776421589155460...
result:
ok 1000 lines
Test #4:
score: 0
Accepted
time: 3285ms
memory: 261916kb
input:
2000 2587627816607030340103003175959756184662 7728753705064569253253827797978613582938 6507847628603052973674714721 6989857636824717968431061258300652290539 4734281027640913533293237760425416005062 9411123735455625690768098631226366597446 8309753930995253536640660321476246470149 63565157427098067709...
output:
1603610451790269237852635641930301658193367441164307312552842461667027137613454 14309943493171496191506053530749878345271155973702143153225815632926701434642842 10414697803791950572309383355053080338229465674803757518 11704102206894264239190418551798088411458157423624785417336589284698838535371266 5...
result:
ok 2000 lines
Test #5:
score: 0
Accepted
time: 4940ms
memory: 261848kb
input:
5000 6701025283447923273597553918313900029215 1618190467906965189844764312914748628527 2135261797018456059451326428589353332126 8027429917075086154217136768450383650445 8263301530632040969183919589286944799002 376886964626613356031779878 1191561726595055348898524031899625958102 453561433135467095374...
output:
10756647971303093856509780939435968749671842310025383400207261624750784751725876 627115945498078452730193858129037650151913122482133071938783012929533045529940 1091921493223233296724616654299408127388059493196845968361252389122720100379070 154375707400033063668088306493199269136326791073281723548116...
result:
ok 5000 lines
Test #6:
score: 0
Accepted
time: 7582ms
memory: 261904kb
input:
10000 260865660295317278841 5232352637620496342310336202478387251106 7108789244285764135987032973912918380 12766535319519586095540974948550152061 5138306300154916887884637635208203681949 7603163140266839847784708214115317398585 149590294591155205497765668766786424787 63283557694500045989299147454323...
output:
16323111740957704392106241109891718054228 6557703685144914472554701877112177422100848067214049191882271294010013621817762 12143115079716078114619105501427985631361994195400195527663921137836417758 39139456824156526604158618001888125076786817219954316014947704612553450312 6324051018379978443719363340...
result:
ok 10000 lines