[CQOI 2018] Nine Links

Description

Question bank link

Give you a \(n\) chain, the rules of the game are:

  1. The first (rightmost) ring can be attached or removed at any time;
  2. If the \(k\) th ring is not removed, and all rings to the right of the \(k\) th ring are removed, then the \(k+1\) th ring ( \(k\) The ring adjacent to the left of the ring) can be installed or removed at will.

Now \(m\) groups of questions, each group of questions give you \(n\) chain, ask you at least how many steps to take down all the rings.

\ (1 \ leq n \ leq 10 ^ 5,1 \ leq m \ leq 10 \)

Solution

The derivation in the mathematics book is very clear:

It is worth noting that \(n\) in the second picture is an odd derivation in which \(\frac{2(1-2^{n+1})}{1-2^2}\) should be \(\frac{1-2^{n+1}}{1-2^2}\)

Good luck to point out mistakes in math books.

Then \(\text{FFT}\) fast power messing around just fine. Isn't playing with \(\text{FFT}\) without \(-O2\) just playing with fire? ? ?

Code

This melon skin code constant is too large to pass on station b.

#include <bits/stdc++.h>
#define dob complex<double>
using namespace std;
const int N = (100000<<2)+5;
const double pi = acos(-1.);

int n, nn, m, len, L, R[N], A[N];
dob a[N], b[N];

void FFT(dob *A, int o) {
    for (int i = 0; i < len; i++) if (i < R[i]) swap(A[i], A[R[i]]);
    for (int i = 1; i < len; i <<= 1) {
        dob wn(cos(pi/i), sin(pi*o/i)), x, y;
        for (int j = 0; j < len; j += (i<<1)) {
            dob w(1, 0);
            for (int k = 0; k < i; k++, w = w*wn) {
                x = A[j+k], y = w*A[i+j+k];
                A[j+k] = x+y, A[i+j+k] = x-y;
            }
        }
    }
}
void work() {
    scanf("%d", &n); nn = n; ++n; m = log(2)*n+5;
    for (L = 0, len = 1; len <= m; len <<= 1) ++L;
    for (int i = 0; i < len; i++) a[i] = b[i] = 0;
    for (int i = 0; i < len; i++) R[i] = (R[i>>1]>>1)|((i&1)<<(L-1));
    a[0] = 1, b[0] = 2;
    while (n) {
        FFT(a, 1), FFT(b, 1);
        if (n&1) for (int i = 0; i <= len; i++) a[i] = a[i]*b[i];
        for (int i = 0; i <= len; i++) b[i] = b[i]*b[i]; n >>= 1;
        FFT(a, -1); FFT(b, -1);
        for (int i = 0; i < len; i++) A[i] = a[i].real()/len+0.5;
        int loc = 0; while (A[loc] && loc < len) A[loc+1] += A[loc]/10, A[loc] %= 10, ++loc;
        for (int i = 0; i < len; i++) a[i] = A[i];
        for (int i = 0; i < len; i++) A[i] = b[i].real()/len+0.5;
        loc = 0; while (A[loc] && loc < len) A[loc+1] += A[loc]/10, A[loc] %= 10, ++loc;
        for (int i = 0; i < len; i++) b[i] = A[i];
    }
    for (int i = 0; i < len; i++) A[i] = a[i].real();
    A[0] -= 1+(!(nn&1));
    for (int i = len-1, flag = 0, sum = 0; i >= 0; i--) {
        sum = sum*10+A[i]; if (sum/3) flag = 1;
        if (flag) printf("%d", sum/3), sum %= 3;
    }
    puts("");
}
int main() {int t; cin >> t; while (t--) work(); return 0; }

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325258468&siteId=291194637