Article Index

CF1997F Chips on a Line 做题笔记

Published on

题目

题解

定义 $N$ 的 Fibonacci 表示 $a_i$:

$$N = \sum a_if_i$$

其中 $f_i$ 为 Fibonacci 数,$f_1 = f_2 = 1$。注意 Fibonacci 表示可能不唯一。

有两个性质:所有操作可撤销 和 所有操作不改变 Fibonacci 表示下的和($\sum a_if_i$)。

首先想想一个放置方案的 cost 是多少。找到 $\sum a_i$ 最小的 Fibonacci 表示,cost 就是 $\sum a_i$。这个表示显然可以从大到小枚举 Fibonacci 数贪心求解,且是唯一的。这个最小表示名为 Zeckendorf 表示。

那现在知道 cost 怎么算之后,我们可以判定出哪些数是需要统计进答案的了。

对于一个数来说,我们想计算有多少种不同的 Fibonacci 表示。设 $f_{i, j, k}$ 表示如果只用前 $i$ 个位,$\sum a_i = j$ 且 $\sum a_if_i = k$ 的方案数。

然后空间会卡,把第一维滚掉。

时间复杂度 $O\left(x \cdot n^2 \cdot f_x\right)$。

代码

/* C++17 is required!
 * By Koicy (https://koicy.ly)
 * Email n@rbtr.ee
 * I've reached the end of my fantasy.

         __    __                             __         _
   _____/ /_  / /_________  ___              / /______  (_)______  __
  / ___/ __ \/ __/ ___/ _ \/ _ \   ______   / //_/ __ \/ / ___/ / / /
 / /  / /_/ / /_/ /  /  __/  __/  /_____/  / ,< / /_/ / / /__/ /_/ /
/_/  /_.___/\__/_/   \___/\___/           /_/|_|\____/_/\___/\__, /
                               SIGN                         /___*/
#ifndef XCODE
constexpr bool _CONSOLE = false;
#else
constexpr bool _CONSOLE = true;
#endif
#define __NO_MAIN__ false
#define __ENABLE_RBLIB__ true
constexpr bool _MTS = false, SPC_MTS = false;
constexpr char EFILE[] = "";
#define FULL(arg) arg.begin(), arg.end()

// :/

signed STRUGGLING([[maybe_unused]] unsigned long TEST_NUMBER) {
  constexpr tp mod = 998244353;
  tp n, x, m; bin >> n >> x >> m;
  vetp fib { 0, 1, 1 };
  for (tp i = 3; i <= 100; ++i) fib.push_back(fib[i - 1] + fib[i - 2]);
  auto Zeckendorf = [&](tp n) -> tp {
    tp ret = 0;
    for (tp i = 100; i >= 1; --i) {
      ret += n / fib[i];
      n %= fib[i];
    }
    return ret;
  };
  vector<vetp> f(n + 1, vetp(fib[x] * n + 1));
  f[0][0] = 1;
  auto mad = [](tp a, tp b) { return a + b >= mod ? a + b - mod : a + b; };
  for (tp i = 1; i <= x; ++i) {
    for (tp j = 1; j <= n; ++j) {
      for (tp k = fib[i]; k < f[j].size(); ++k) {
        f[j][k] = mad(f[j][k], f[j - 1][k - fib[i]]);
      }
    }
  }
  tp tar = 0;
  for (tp j = 1; j < f[n].size(); ++j) {
    if (Zeckendorf(j) == m) tar = mad(tar, f[n][j]);
  }
  bin << tar << '\n';
  return 0;
}

void MIST() {
}

// :\ */

No comments

Post a comment