首页 > 其他分享 >QOJ 4824 Bracket-and-bar Sequences

QOJ 4824 Bracket-and-bar Sequences

时间:2024-05-30 21:25:24浏览次数:31  
标签:std bar int 4824 texttt Bracket solve return ll

考虑到这个实际上没有特别好的表示方法。
不如从 \(n\le 25\),猜想合法的序列数量不多。

考虑对这个计数。
类似于合法括号序计数,考虑把串拆为 \(\texttt{(}\cdots\texttt{|}\cdots\texttt{)}\cdots\) 来考虑。
那么令 \(f_i\) 表示 \(i\) 对 \(\texttt{(|)}\) 组成的序列的数量。
有转移 \(f_i = \sum\limits_{j = 0}^{n - 1}\sum\limits_{k = 0}^{n - 1 - j} f_j f_k f_{n - 1 - j - k}\)。

跑出来能发现 \(f_{25} = 1031147983159782228\le 2\times 10^{18}\),那就可以对于不同的序列给一个不同的编号了。

先考虑 encode
考虑类似上面转移,拆成 \(\texttt{(}\cdots\texttt{|}\cdots\texttt{)}\cdots\),令这 \(3\) 部分中间的 \(\texttt{(|)}\) 的数量分别为 \(c_1, c_2, c_3\)。
首先类似转移,对于 \(i < c_1\lor (i = c_1\land j < c2)\) 的情况,把 \(f_i f_j f_{n - 1 - i - j}\) 都加上,这样子就能确定对应的 \(c_1 = i, c_2 = j\) 了。
然后考虑递归构造,得到三部分的权值 \(v_1, v_2, v_3\),因为还要区分出这 \(3\) 部分的权值,再加上 \(f_{c_3}(f_{c_2}v_1 + v_2) + v_3\) 即可。

对于 decode
考虑按照上面求 \(f_n\) 的顺序枚举 \(i, j\),如果满足此时 \(s < f_i f_j f_{n - 1 - i - j}\),就能知道 \(c_1 = i, c_2 = j, c_3 = n - 1 - i - j\)。
然后再根据上面的操作就能推出 \(v_1, v_2, v_3\),递归构造即可。
如果 \(s\ge f_i f_j f_{n - 1 - i - j}\),那么就说明不是这对,\(s\) 减去这个值即可。

\(x \le 1031147983159782228\le 2\times 10^{18}\),时间复杂度 \(\mathcal{O}(n^2)\)。

#include<bits/stdc++.h>
using ll = long long;
const int maxn = 28;
ll f[maxn];
namespace Encode {
   ll solve(int n, std::string s) {
      if (! n)
         return 0;
      int p1 = 0, p2 = 0;
      for (int i = 0, cnt = 0; ; i++) {
         cnt += s[i] == '(', cnt -= s[i] == ')';
         if (cnt == 1 && s[i] == '|') p1 = i;
         if (! cnt) {p2 = i; break;}
      }
      int c1 = (p1 - 1) / 3, c2 = (p2 - p1 - 1) / 3, c3 = (n * 3 - 1 - p2) / 3;
      ll val = 0;
      for (int i = 0; i < n; i++)
         for (int j = 0; i + j < n; j++) {
            if (i == c1 && j == c2)
               return (solve(c1, s.substr(1, c1 * 3)) * f[c2] + solve(c2, s.substr(p1 + 1, c2 * 3))) * f[c3] + solve(c3, s.substr(p2 + 1, c3 * 3))
                      + val;
            val += f[i] * f[j] * f[n - 1 - i - j];
         }
      return -1;
   }
   inline void Main() {
      int n; std::string s;
      std::cin >> n >> s;
      std::cout << solve(n, s) << '\n';
   }
   inline void main() {
      f[0] = 1;
      for (int i = 1; i <= 25; i++)
         for (int j = 0; j < i; j++)
            for (int k = 0; j + k < i; k++)
               f[i] += f[j] * f[k] * f[i - 1 - j - k];
      int Ti;
      for (std::cin >> Ti; Ti--; ) Main();
   }
}
namespace Decode {
   std::string solve(int n, ll s) {
      if (! n)
         return "";
      for (int i = 0; i < n; i++)
         for (int j = 0; i + j < n; j++) {
            if (s < f[i] * f[j] * f[n - 1 - i - j]) {
               ll s3 = s % f[n - 1 - i - j], s2 = (s / f[n - 1 - i - j]) % f[j], s1 = s / f[n - 1 - i - j] / f[j];
               return "(" + solve(i, s1) + "|" + solve(j, s2) + ")" + solve(n - 1 - i - j, s3);
            }
            s -= f[i] * f[j] * f[n - 1 - i - j];
         }
      return "-1";
   }
   inline void Main() {
      int n; ll s;
      std::cin >> n >> s;
      std::cout << solve(n, s) << '\n';
   }
   inline void main() {
      f[0] = 1;
      for (int i = 1; i <= 25; i++)
         for (int j = 0; j < i; j++)
            for (int k = 0; j + k < i; k++)
               f[i] += f[j] * f[k] * f[i - 1 - j - k];
      int Ti;
      for (std::cin >> Ti; Ti--; ) Main();
   }
}
int main() {
   std::ios::sync_with_stdio(false);
   std::cin.tie(0), std::cout.tie(0);
   std::string tp; std::cin >> tp;
   tp == "encode" ? Encode::main() : Decode::main();
   return 0;
}

标签:std,bar,int,4824,texttt,Bracket,solve,return,ll
From: https://www.cnblogs.com/rizynvu/p/18223234

相关文章

  • 容器组件Tabs如何自定义 tabBar-高亮切换
    1.TabBar如果放在底部的话,一般会显示图形和文字,甚至有特殊的图标,如果要实现此类效果,就需要自定义tabBarTabs(){TabContent(){//内容略}.tabBar(this.tabBarBuilder())}@BuildertabBarBuilder(){//自定义的Tabbar结构}2.自定义TabBa......
  • Windows 7 任务栏开发 之 进度条(Progress Bar)
         上一篇我们完成了“覆盖图标”(OverlayIcon)的相关开发,本篇我们将对进度条特性进行研究。在使用IE下载文件时,任务栏图标会同步显示当前下载进度(如下图)。那么在应用程序中如何实现这个效果呢? 下载状态 TaskbarManager.SetProgressValue 方法      在Tas......
  • JUC框架(Semaphore、CountDownLatch、CyclicBarrier)
    文章目录Semaphore(信号量)Semaphore介绍Semaphore基本概念Semaphore使用场景Semaphore示例CountDownLatch(计数器/闭锁)CountDownLatch介绍CountDownLatch基本概念CountDownLatch使用场景CountDownLatch基本方法CountDownLatch示例CyclicBarrier(循环栅栏)Cyclic......
  • 使用 Unity Barracuda 和 Compute Shader,Yolov2 进行高效物体识别
    前言通过整合UnityBarracuda和TinyYOLOv2模型,开发者可以在Unity中实现高效的实时物体识别功能。这种技术不仅可以增强游戏和应用的交互性,还可以应用于虚拟现实(VR)和增强现实(AR)等创新项目中,为用户创造更加沉浸和动态的体验。TinyYOLOv2模型概述TinyYOLOv2是YOLO(You......
  • wxPython==4.2.1 aui.AuiToolBar 如何去掉烦人的抓手?
    aui.AuiToolBar如何去掉烦人的抓手?最近在用wxPython做一些GUI小应用,发现工具栏总有几个点(抓手),很影响美观,如下:目前官方没有提供隐藏抓手的功能,需要更改源码的auibar.py文件注释掉对应代码。如下:#注释这句,大致在auibar.py+3480(不同版本可能有差异)#self._art.DrawGrip......
  • Minecraft中BossBar、Recipe的底层实现与扩展应用(学习笔记)
    看到有位博主写得很不错,直接上链接:《进度条与自定义合成表》本人在学习这篇博客的基础上进行实践与验证(使用1.12Bukkit接口开发),对上面的文件做几点总结与补充:正如文中所说,一定要记得在插件卸载时对注册的进度条和合成配方进行注销。文中所说的对进度条进行卸载的方法Buk......
  • Semantic Kernel入门系列:利用Handlebars创建Prompts functions
    引言本章我们将学习通过HandlebarsPromptsTemplate来创建Promptsfunctions。什么是Handlebars?Handlebars是一个流行的JavaScript模板引擎,它允许你通过在HTML中使用简单的占位符来创建动态的HTML。它使用模板和输入对象来生成HTML或其他文本格式。Handlebars模板看......
  • 【unity】在EditorWindow添加自定义的Toolbar按钮
    好久没写了,最近做工具,写了个EditorWindow,为了让使用者方便查看这个工具的文档,想着在导航栏加个问号按钮,点一下打开说明文档就完事~查了下unity手册,发现Unity提供了一个ShowButton 方法,用于在自定义Editor窗口的工具栏中添加自定义内容,下面是实现的例子:privateGUIStyle......
  • 谷歌与火狐Hackbar插件下载安装(收费前残留版本)
    参考:https://www.cnblogs.com/cainiao-chuanqi/p/14016644.htmlhacker插件下载地址:https://github.com/Mr-xn/hackbar2.1.3以谷歌为例:将解压后中的文件拖入谷歌扩展程序中点击详情找到此处,点击链接会跳转到插件在谷歌中安装的位置,打开hackbar-panel.js文件(如果没有,在当前......
  • dxNavBar1做导航菜单,类QQ的抽屉效果(23)
     从右边的项鼠标拖到左边的分组内然后修改分组/项的名称Caption ......