제출 #1350104

#제출 시각아이디문제언어결과실행 시간메모리
1350104biankFibonacci representations (CEOI18_fib)C++20
65 / 100
4094 ms66284 KiB
#include <bits/stdc++.h>
 
using namespace std;
 
#define forsn(i, s, n) for (int i = int(s); i < int(n); i++)
#define forn(i, n) forsn(i, 0, n)
#define dforsn(i, s, n) for (int i = int(n) - 1; i >= int(s); i--)
#define dforn(i, n) dforsn(i, 0, n)
 
using vi = vector<int>;
using ii = pair<int, int>;
using vii = vector<ii>;
using ll = long long;
using ld = long double;
using vll = vector<ll>;
using vb = vector<bool>;
using pll = pair<ll, ll>;
using bint = __int128;

#define sz(x) int(x.size())
#define all(x) begin(x), end(x)

#define pb push_back
#define eb emplace_back

#define fst first
#define snd second

const int MOD = 1e9 + 7;
const int MAX_A = 1e9 + 50;

const int T = 3;

using mat = array<array<int, T>, T>;

auto f = [](int cnt) {
    mat a;
    map<int, map<int, int>> idx;
    int id = 0;
    forn(carryToMe, 2) forn(carryToPrev, 2) {
        if (carryToMe >= carryToPrev) idx[carryToMe][carryToPrev] = id++;
    }
    forn(i, T) forn(j, T) a[i][j] = 0;
    forn(carryToMe, 2) forn(carryToPrev, 2) if (carryToMe >= carryToPrev) {
        forn(use, 2) {
            int pass = carryToMe + cnt - use;
            if (pass >= 0 && pass + carryToPrev < 2) {
                assert(pass + carryToPrev >= pass);
                int from = idx[carryToMe][carryToPrev];
                int to = idx[pass + carryToPrev][pass];
                a[from][to]++;
            }
        }
    }
    return a;
};

const mat ZERO = f(0), ONE = f(1);

const mat NEUTR = []() {
    mat a;
    forn(i, T) forn(j, T) a[i][j] = i == j;
    return a;
}();

vector<mat> powersOfZero;

mat mul(mat a, mat b) {
    mat c;
    forn(i, T) forn(j, T) c[i][j] = 0;
    forn(i, T) forn(k, T) forn(j, T) {
        c[i][j] = (c[i][j] + 1LL * a[i][k] * b[k][j]) % MOD;
    }
    return c;
}

mat value(int k) {
    mat r = ONE;
    forn(i, 30) if (k >> i & 1) r = mul(r, powersOfZero[i]);
    return r;
}

set<int> fib;
vi vals;
 
void fakeAdd(int x) {
    if (fib.count(x)) {
        fib.erase(x);
        fakeAdd(x + 1);
        if (x > 2) fakeAdd(x - 2);
        else if (x == 2) fakeAdd(x - 1);
        return;
    }
    if (fib.count(x - 1)) {
        fib.erase(x - 1);
        fakeAdd(x + 1);
        return;
    }
    if (fib.count(x + 1)) {
        fib.erase(x + 1);
        fakeAdd(x + 2);
        return;
    }
    fib.insert(x);
    vals.pb(x);
}

const int SZ = 1 << 17;

mat st[2 * SZ];

void upd(int p, mat v) {
    for (st[p += SZ] = v; p /= 2; ) {
        st[p] = mul(st[2 * p + 1], st[2 * p]);
    }
}

int pos(int x) {
    auto it = lower_bound(all(vals), x);
    assert(it != end(vals) && *it == x);
    return int(it - begin(vals));
}

void erase(int x) {
    auto it = fib.lower_bound(x);
    upd(pos(x), NEUTR), it = fib.erase(it);
    if (it != end(fib)) {
        upd(pos(*it), value(*it - *prev(it) - 1));
    }
}

void insert(int x) {
    auto it = fib.lower_bound(x);
    if (it != end(fib)) {
        upd(pos(*it), value(*it - x - 1));
    }
    upd(pos(x), value(x - *prev(it) - 1));
    fib.insert(x);
}

void add(int x) {
    if (fib.count(x)) {
        erase(x);
        add(x + 1);
        if (x > 2) add(x - 2);
        else if (x == 2) add(x - 1);
        return;
    }
    if (x > 1 && fib.count(x - 1)) {
        erase(x - 1);
        add(x + 1);
        return;
    }
    if (fib.count(x + 1)) {
        erase(x + 1);
        add(x + 2);
        return;
    }
    insert(x);
}

int main() {
    ios::sync_with_stdio(0); 
    cin.tie(0); cout.tie(0);
    
    powersOfZero = {ZERO};
    forn(i, 32) powersOfZero.pb(mul(powersOfZero.back(), powersOfZero.back()));
    
    int n;
    cin >> n;
    vi a(n);
    forn(i, n) cin >> a[i];
    
    forn(i, n) fakeAdd(a[i]);
    
    sort(all(vals));
    vals.erase(unique(all(vals)), end(vals));
    
    forn(i, 2 * SZ) st[i] = NEUTR;
    fib = {0};
    forn(i, n) {
        add(a[i]);
        cout << st[1][0][0] << "\n";
    }
    
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...