QOJ.ac
QOJ
ID | Problem | Submitter | Result | Time | Memory | Language | File size | Submit time | Judge time |
---|---|---|---|---|---|---|---|---|---|
#617441 | #9225. Fibonacci Fusion | ucup-team5062# | TL | 2659ms | 15644kb | C++17 | 7.7kb | 2024-10-06 15:34:42 | 2024-10-06 15:34:43 |
Judging History
answer
#include <array>
#include <cmath>
#include <vector>
#include <cassert>
#include <cstdint>
#include <iostream>
#include <algorithm>
using namespace std;
const uint64_t MOD = 18446744069414584321ULL;
class modint {
private:
uint64_t x;
public:
modint() : x(0) {}
modint(uint64_t x_) : x(x_) {}
uint64_t val() const { return x; }
modint& operator+=(const modint& m) {
uint64_t y = x + m.x;
x = (y >= x ? y : y - MOD);
return *this;
}
modint& operator-=(const modint& m) {
uint64_t y = x - m.x;
x = (y <= x ? y : y + MOD);
return *this;
}
modint& operator*=(const modint& m) {
__uint128_t y = __uint128_t(x) * m.x;
x = y % MOD; // TODO: MAKE IT FASTER!
return *this;
}
modint operator+(const modint& m) const {
return modint(*this) += m;
}
modint operator-(const modint& m) const {
return modint(*this) -= m;
}
modint operator*(const modint& m) const {
return modint(*this) *= m;
}
modint pow(uint64_t b) const {
modint res(1), a(*this);
while (b != 0) {
if (b & 1) {
res *= a;
}
a *= a;
b >>= 1;
}
return res;
}
modint inv() const {
return pow(MOD - 2);
}
};
const modint GEN = modint(7);
const modint GEN_INV = modint(7).inv();
vector<modint> fft(int n, const vector<modint>& x, bool inv) {
// step #1. preparation
modint root = (!inv ? GEN : GEN_INV);
vector<modint> z(n);
for (int i = 0; i < n; i++) {
int r1 = 1, r2 = n / 2, cur = 0;
while (r2 >= 1) {
if ((i & r1) != 0) {
cur += r2;
}
r1 <<= 1;
r2 >>= 1;
}
z[cur] = x[i];
}
// step #2. calculation
for (int b = 2; b <= n; b *= 2) {
vector<modint> pows(b);
pows[0] = 1;
pows[1] = root.pow((MOD - 1) / b);
for (int i = 2; i < b; i++) {
pows[i] = pows[i - 1] * pows[1];
}
for (int stt = 0; stt < n; stt += b) {
for (int i = 0; i < b / 2; i++) {
modint r1 = z[stt + i] + pows[i + 0 * b / 2] * z[stt + i + b / 2];
modint r2 = z[stt + i] + pows[i + 1 * b / 2] * z[stt + i + b / 2];
z[stt + i + 0 * b / 2] = r1;
z[stt + i + 1 * b / 2] = r2;
}
}
}
// step #3. finalize
if (inv) {
modint SCALE = modint(n).inv();
for (int i = 0; i < n; i++) {
z[i] *= SCALE;
}
}
return z;
}
vector<int64_t> convolution_unsigned(const vector<int32_t>& a, const vector<int32_t>& b) {
int n = int(a.size()) + int(b.size()) - 1;
int sz = (n >= 2 ? 1 << (32 - __builtin_clz(n - 1)) : 1);
vector<modint> va(sz), vb(sz);
for (int i = 0; i < int(a.size()); i++) {
va[i] = a[i];
}
for (int i = 0; i < int(b.size()); i++) {
vb[i] = b[i];
}
va = fft(sz, va, false);
vb = fft(sz, vb, false);
for (int i = 0; i < sz; i++) {
va[i] *= vb[i];
}
va = fft(sz, va, true);
vector<int64_t> c(n);
for (int i = 0; i < n; i++) {
c[i] = va[i].val();
}
return c;
}
const int DIGITS = 6;
const int DIGITS_POW = 1'000'000;
class bigint {
private:
int size;
vector<int32_t> v;
void normalize() {
while (size >= 2 && v.back() == 0) {
v.pop_back();
size--;
}
}
public:
explicit bigint() : v() {}
explicit bigint(const string& s) {
size = (s.size() + DIGITS - 1) / DIGITS;
v = vector<int32_t>(size, 0);
for (int i = 0; i < int(s.size()); i++) {
int idx = (s.size() - i - 1) / DIGITS;
v[idx] = v[idx] * 10 + int(s[i] - '0');
}
normalize();
}
string to_string() const {
string res;
for (int i = 0; i < size; i++) {
int x = v[i];
for (int j = 0; j < DIGITS; j++) {
res += char(x % 10 + '0');
x /= 10;
}
}
while (int(res.size()) >= 2 && res.back() == '0') {
res.pop_back();
}
reverse(res.begin(), res.end());
return res;
}
bool operator==(const bigint& b) const {
return v == b.v;
}
bool operator!=(const bigint& b) const {
return v != b.v;
}
bool operator<(const bigint& b) const {
if (size != b.size) {
return size < b.size;
}
for (int i = size - 1; i >= 0; i--) {
if (v[i] != b.v[i]) {
return v[i] < b.v[i];
}
}
return false;
}
bool operator>(const bigint& b) const {
if (size != b.size) {
return size > b.size;
}
for (int i = size - 1; i >= 0; i--) {
if (v[i] != b.v[i]) {
return v[i] > b.v[i];
}
}
return false;
}
bool operator<=(const bigint& b) const {
if (size != b.size) {
return size < b.size;
}
for (int i = size - 1; i >= 0; i--) {
if (v[i] != b.v[i]) {
return v[i] < b.v[i];
}
}
return true;
}
bool operator>=(const bigint& b) const {
if (size != b.size) {
return size > b.size;
}
for (int i = size - 1; i >= 0; i--) {
if (v[i] != b.v[i]) {
return v[i] > b.v[i];
}
}
return true;
}
bigint& operator+=(const bigint& b) {
if (size < b.size) {
v.resize(b.size);
size = b.size;
}
int carry = 0;
for (int i = 0; i < size; i++) {
v[i] += (i < b.size ? b.v[i] : 0) + carry;
if (v[i] >= DIGITS_POW) {
v[i] -= DIGITS_POW;
carry = 1;
} else {
carry = 0;
}
}
if (carry == 1) {
v.push_back(1);
size += 1;
}
return *this;
}
bigint& operator-=(const bigint& b) {
assert(size >= b.size);
int carry = 0;
for (int i = 0; i < size; i++) {
v[i] -= (i < b.size ? b.v[i] : 0) + carry;
if (v[i] < 0) {
v[i] += DIGITS_POW;
carry = 1;
} else {
carry = 0;
}
}
assert(carry == 0);
normalize();
return *this;
}
bigint& operator*=(const bigint& b) {
vector<int64_t> res = convolution_unsigned(v, b.v);
for (int i = 0; i < int(res.size()); i++) {
if (i == int(res.size()) - 1 && res[i] >= DIGITS_POW) {
res.push_back(0);
}
res[i + 1] += res[i] / DIGITS_POW;
res[i] %= DIGITS_POW;
}
size = res.size();
v.resize(size);
for (int i = 0; i < size; i++) {
v[i] = res[i];
}
normalize();
return *this;
}
bigint operator+(const bigint& b) const {
return bigint(*this) += b;
}
bigint operator-(const bigint& b) const {
return bigint(*this) -= b;
}
bigint operator*(const bigint& b) const {
return bigint(*this) *= b;
}
double log10() const {
double p = 0.0, q = 1.0;
for (int i = size - 1; i >= 0; i--) {
p += v[i] * q;
q /= DIGITS_POW;
}
return (size - 1) * DIGITS + std::log10(p);
}
};
array<bigint, 2> fib(int n) {
if (n == 0) {
return {bigint("0"), bigint("1")};
}
array<bigint, 2> z = fib(n / 2);
bigint a = z[0] * z[0];
bigint b = z[0] * z[1];
bigint c = z[1] * z[1];
if (n % 2 == 0) {
return {b + b - a, a + c};
}
return {a + c, b + b + c};
}
int fib_index(double x) {
// n = 10^x
double z = x + log10(5) / 2;
double logphi = log10((1 + sqrt(5)) / 2);
return z / logphi + 0.8;
}
long long solve(int N, vector<bigint>& A) {
// step #1. sort and compress
sort(A.begin(), A.end());
vector<bigint> B;
vector<int> C;
int pre = 0;
for (int i = 1; i <= N; i++) {
if (i == N || A[i] != A[i - 1]) {
B.push_back(A[i - 1]);
C.push_back(i - pre);
pre = i;
}
}
int Z = B.size();
// step #2. check answer
long long ans = 0;
for (int i = 0; i < Z; i++) {
int x = fib_index(B[i].log10());
array<bigint, 2> val = fib(x);
for (int j = 0; j < 2; j++) {
if (B[i] <= val[j] && val[j] < B[i] + B[i]) {
bigint target = val[j] - B[i];
int pos = lower_bound(B.begin(), B.end(), target) - B.begin();
if (B[pos] == target) {
ans += 1LL * C[i] * C[pos];
}
} else if (val[j] == B[i] + B[i]) {
ans += 1LL * C[i] * (C[i] - 1) / 2;
}
}
}
return ans;
}
int main() {
int N;
cin >> N;
vector<bigint> A(N);
for (int i = 0; i < N; i++) {
string str;
cin >> str;
A[i] = bigint(str);
}
long long ans = solve(N, A);
cout << ans << endl;
return 0;
}
Details
Tip: Click on the bar to expand more detailed information
Test #1:
score: 100
Accepted
time: 1ms
memory: 3740kb
input:
6 50 8 8 5 72 354224848179261915070
output:
4
result:
ok 1 number(s): "4"
Test #2:
score: 0
Accepted
time: 2659ms
memory: 11580kb
input:
28 200878223506436882933619847964496455022155117513398820563747455993172799881403389571477889821109288771413214004090719097929400406252135763028179112130390003528046316900603668569910008417315162907579003880220844686222148696041857432602133894827753998572080650383305777912447151917272483538029469449...
output:
27
result:
ok 1 number(s): "27"
Test #3:
score: 0
Accepted
time: 2438ms
memory: 10384kb
input:
5187 2640352926124261912741724778991366987330659389621881876017670644497364093930668042530271338851702874394631009332660937266680740235862107353443518003194307853104942996827176097428402408674756368623972812842571069642405111849826172879369776309763468485788964245903781380419155348915131587410703749...
output:
6073
result:
ok 1 number(s): "6073"
Test #4:
score: 0
Accepted
time: 32ms
memory: 15644kb
input:
200000 2 2 2 2 1 2 1 1 2 2 1 1 1 2 2 1 1 2 1 1 2 2 1 2 2 2 1 1 1 1 2 2 1 2 1 2 1 1 2 2 1 1 1 2 1 1 2 1 2 2 2 2 1 2 2 1 1 1 2 1 1 1 1 1 2 1 2 2 1 1 1 2 2 2 1 1 2 1 1 2 1 2 1 1 1 2 2 2 1 1 1 1 2 1 2 1 1 2 2 1 1 2 1 1 2 1 2 2 1 2 1 2 2 1 1 2 1 1 1 2 2 2 1 2 2 1 1 2 2 2 2 1 2 1 1 2 1 2 2 1 1 1 1 2 2 2 2...
output:
15003749259
result:
ok 1 number(s): "15003749259"
Test #5:
score: -100
Time Limit Exceeded
input:
200000 944176313232170622314 2590599414036674999101 753315073608896000424 9299685298577430049245 9361800333778142620806 8988699166328904060999 9606920674025578304023 4203331868598952026136 5183047027116137697788 3968714342776915029801 8130984095583566992354 3206443643596048048798 6248561214283254355...