CF1810H Last Number
大难题,但是非常的有意思。思路来自
题意
对于一个 可重 集合
给定
做法
首先观察题目给出的操作序列,容易发现这些操作是分为两部分的。记第
这部分先按下不表,转而考察
接下来,考虑前半部分操作。首先,
你可以把生成
那么我们就获得了一种优雅的方法生成
接下来,只需要结合上面对于后半部分操作的结论即可。容易得出,考虑我们在第
那么我们要支持快速求
代码
// Author: kyEEcccccc #include <bits/stdc++.h> using namespace std; using LL = long long; using ULL = unsigned long long; #define F(i, l, r) for (int i = (l); i <= (r); ++i) #define FF(i, r, l) for (int i = (r); i >= (l); --i) #define MAX(a, b) ((a) = max(a, b)) #define MIN(a, b) ((a) = min(a, b)) #define SZ(a) ((int)((a).size()) - 1) constexpr int K = 23; struct SegInfo { int len, odd, even, sum; SegInfo operator +(const SegInfo& o) const { if (len % 2 == 0) return {len + o.len, odd + o.odd, even + o.even, sum + o.sum}; else return {len + o.len, odd + o.even, even + o.odd, sum + o.sum}; } }; SegInfo f[2][K]; void init(void) { f[0][0] = {1, 0, 0, 0}; f[1][0] = {1, 1, 0, 1}; F(i, 1, K - 1) { f[0][i] = f[1][i - 1] + f[0][i - 1]; f[1][i] = f[1][i - 1] + f[1][i - 1] + f[0][i - 1]; } int sum = 0; F(i, 0, K - 1) sum += f[0][i].len; } int find_p(int n) { SegInfo all = {0, 0, 0, 0}; F(i, 0, K - 1) { SegInfo nw = all + f[0][i]; if (n - nw.sum <= 2 * nw.len) { int t = 0; FF(j, i - 1, 0) { if (t == 0) { nw = all + f[1][j]; if (n - nw.sum <= 2 * nw.len) t = 1; else { t = 0; all = nw; } } else { nw = all + f[1][j]; if (n - nw.sum <= 2 * nw.len) t = 1; else { all = nw; nw = all + f[1][j]; if (n - nw.sum <= 2 * nw.len) t = 1; else { t = 0; all = nw; } } } } return all.len + 1; } all = nw; } assert(0); } SegInfo getinfo(int m) { SegInfo all = {0, 0, 0, 0}; F(i, 0, K - 1) { if (all.len + f[0][i].len < m) { all = all + f[0][i]; continue; } int t = 0; FF(j, i - 1, 0) { if (t == 0) { if (all.len + f[1][j].len >= m) t = 1; else { t = 0; all = all + f[1][j]; } } else { if (all.len + f[1][j].len >= m) t = 1; else { all = all + f[1][j]; if (all.len + f[1][j].len >= m) t = 1; else { t = 0; all = all + f[1][j]; } } } } return all + f[t][0]; } assert(0); } void work(void) { int n; cin >> n; if (n == 1) return cout << "1\n", void(); if (n == 2) return cout << "1\n", void(); int p = find_p(n); SegInfo xp = getinfo(p), xn = getinfo(n - 1); if ((n - p) % 2 == 0) { if (p % 2 == 0) cout << p - xn.odd + xp.odd << '\n'; else cout << p - xn.even + xp.even << '\n'; } else { if (p % 2 == 0) cout << n - xp.sum - p - xn.even + xp.even << '\n'; else cout << n - xp.sum - p - xn.odd + xp.odd << '\n'; } } signed main(void) { // freopen(".in", "r", stdin); // freopen(".out", "w", stdout); ios::sync_with_stdio(0), cin.tie(nullptr); init(); int _; cin >> _; while (_--) work(); return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现