首页 > 其他分享 >[ABC312] 题解 [D~Ex]

[ABC312] 题解 [D~Ex]

时间:2023-07-30 20:23:46浏览次数:40  
标签:sz 10 int 题解 ABC312 cin Ex include dp

[ABC312] 题解 [D~Ex]

D - Count Bracket Sequences

一个括号序列 \(s\) 包含 (, ), ?? 可以填任意括号,问你填完后有多少种合法序列方式。

这是一个 Classical 的 括号序列 DP,使用这个状态表示可以解决很多括号序列问题:

\(dp[i][j]\) 表示已经摆好了前 \(i\) 个字符,有 \(j\) 个没有匹配的左括号的方案数。

\[dp[i][j] = \left\{\begin{matrix} dp[i - 1][j - 1]&, s[i] = ( \\ dp[i - 1][j + 1]&, s[i] = )\\ dp[i - 1][j - 1] + dp[i - 1][j + 1]&,s[i] = ? \end{matrix}\right. \]

if(s[1] == '(') dp[1][1] = 1;
if(s[1] == ')') return cout << 0 << '\n', 0;
if(s[1] == '?') dp[1][1] = 1;
for(int i = 2; i <= n; i ++) {
    for(int j = 0; j <= n; j ++) {
        if(s[i] == '?') {
            if(j > 0) dp[i][j] = dp[i - 1][j - 1];
            dp[i][j] = (dp[i][j] + dp[i - 1][j + 1]) % mod;
        }
        if(s[i] == ')') dp[i][j] = dp[i - 1][j + 1];
        if(s[i] == '(' && j > 0) dp[i][j] = dp[i - 1][j - 1];
    }
}
cout << dp[n - 1][0] << '\n';

E - Tangency of Cuboids

观察到 \(M\le 100\rightarrow M^3\le 10^6\),考虑每一个单位格子。

由于立方体不相交,所以一个单位格子最多属于一个立方体,枚举每一个单位格子的四周,如果有一个单位格子的四周有单位格子属于不同的立方体,那么这两个立方体有相同的面。

所以直接枚举即可,时间复杂度:\(O(N + M^3)\)。

#include <iostream>
#include <set>
using namespace std;
const int N = 100 + 10, M = 1e5 + 10;

set<int> s[M];
int dx[] = {1, 0, 0}, dy[] = {0, 1, 0}, dz[] = {0, 0, 1}, n, a[N][N][N]; // 等价于六个方向

signed main()
{
    cin >> n;
    for(int y = 1; y <= n; y ++) {
        int x1, y1, z1, x2, y2, z2;
        cin >> x1 >> y1 >> z1 >> x2 >> y2 >> z2;
        for(int i = x1 + 1; i <= x2; i ++)    
            for(int j = y1 + 1; j <= y2; j ++)
                for(int k = z1 + 1; k <= z2; k ++)
                    a[i][j][k] = y;
    }
    for(int i = 1; i <= 100; i ++)
        for(int j = 1; j <= 100; j ++)
            for(int k = 1; k <= 100; k ++)
                for(int p = 0; p < 3; p ++)
                    if(a[i][j][k] && a[i + dx[p]][j + dy[p]][k + dz[p]] && a[i][j][k] != a[i + dx[p]][j + dy[p]][k + dz[p]])
                        s[a[i][j][k]].insert(a[i + dx[p]][j + dy[p]][k + dz[p]]),
                        s[a[i + dx[p]][j + dy[p]][k + dz[p]]].insert(a[i][j][k]);
    for(int i = 1; i <= n; i ++)
        cout << s[i].size() << '\n';
    return 0;
}

F - Cans and Openers

首先贪心地把所有免费的 all in,然后尝试用开罐器+普通罐替换最劣的拉环罐,这样枚举一定可以找到最优解,代码丑,不放了。

也可以枚举要用几个开罐器,然后二分能够替换多少个普通罐。

时间复杂度:\(O(N\log N)\)。

G - Avoid Straight Line

第一次正赛切 G。

首先容斥,考虑有多少个三元组在同一条路径上,这种三元组计数问题一般枚举中间点,答案的贡献来源有二:

  1. 子树内节点与子树外节点组合;
  2. 不相同子树的两个子节点组合;

第一个乘法原理很好做,第二个情况考虑前缀和,时间复杂度:\(O(N)\)。

// Problem: G - Avoid Straight Line
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2023-07-29 21:03:34

#include <iostream>
#include <queue>
#define int long long
using namespace std;
const int N = 2e5 + 10;

int n;
vector<int> g[N];

int sz[N];
int ans;
void dfs(int u, int fa)
{
    sz[u] = 1;
    for(int v : g[u])
    {
        if(v == fa) continue;
        dfs(v, u);
        sz[u] += sz[v];
    }
    sz[1] = n;
    ans -= (sz[u] - 1) * (n - sz[u]);
    int sum = 0;
    for(int v : g[u])
    {
        if(v == fa) continue;
        ans -= sz[v] * sum;
        sum += sz[v];
    }
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1, a, b; i < n; i ++)
    {
        cin >> a >> b;
        g[a].push_back(b), g[b].push_back(a);
    }
    ans = n * (n - 1) * (n - 2) / 6;
    dfs(1, 1);
    cout << ans << '\n';
    return 0;
}

Ex - snukesnuke

考虑每一个字符串的最小循环节,可以发现,如果两个字符串的最小循环节都不相同,那么无论如何它们两个都不会出现冲突,所以可以把每一种循环节单独处理,对于每一种循环节可以使用一个倍增的数组 \(f\),\(f_i\) 表示当前循环节,循环了 \(i\) 次的字符串至少需要多少次操作能够合法,遍历的时候直接暴力跳即可,发现计算次数是调和级数,所以时间复杂度为:\(O(n\log n)\),但是标记每个点是否被选取需要用 std::set,所以实际时间复杂度为:\(O(n\log^2 n)\)。

// Problem: Ex - snukesnuke
// Author: Moyou
// Copyright (c) 2023 Moyou All rights reserved.
// Date: 2023-07-30 19:05:10

#include <algorithm>
#include <iostream>
#include <queue>
#include <set>
#include <unordered_map>
// #define int long long
#define x first
#define y second
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5 + 10;

int n, ne[N];
unordered_map<string, int> h;
int idx;
int get(string s) {if(!h.count(s)) h[s] = ++ idx; return h[s];}
vector<PII> cir[N];
string s[N];
int Max[N];

void kmp(int x)
{
    int n = s[x].size();
    for(int i = 1, j = 0; i < n; i ++) {
        while(j && s[x][i] != s[x][j]) j = ne[j - 1];
        if(s[x][i] == s[x][j]) j ++;
        ne[i] = j;
    }
    int id = get(s[x].substr(0, ((n % (n - ne[n - 1])) ? n : n - ne[n - 1])));
    cir[id].push_back({n, x});
    Max[id] = max(Max[id], n);
}

int ans[N], f[N];
set<int> st;

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i ++)
        cin >> s[i];
    for(int i = 1; i <= n; i ++)
        kmp(i);
    
    for(int i = 1; i <= idx; i ++) {
        for(int j = 1; j <= Max[i]; j ++)
            f[j] = 1;
        st.clear();
        st.insert(0);
        for(auto [len, id] : cir[i]) {
            while(st.find(f[len] * len) != st.end()) f[len] ++;
            st.insert(f[len] * len), ans[id] = f[len];
        }
    }
    for(int i = 1; i <= n; i ++)
        cout << ans[i] << ' ';
    cout << '\n';    
    return 0;
}

标签:sz,10,int,题解,ABC312,cin,Ex,include,dp
From: https://www.cnblogs.com/MoyouSayuki/p/17591928.html

相关文章

  • BZOJ 4321 queue2 题解
    在硬盘里翻到了当时没推完的这个题,今天补完了最后几步。题目链接:https://hydro.ac/d/bzoj/p/4321对任意相邻两个元素差的绝对值不为\(1\)的\(n\)阶排列计数。\(\mathcal{O}(n^2)\)做法是考虑按照值域由小到大逐步插入,记录\(f_{i,j}\)为长度为\(i\)的排列,一共有\(j\)......
  • bitwarden 私有化部署android无法登陆问题解决
    安卓版bitwarden安装使用中登陆提示“发生错误。Exceptionmessage:java.security.cert.CertPathValidatorException:Trustanchorforcertificationpathnotfound.”这个错误是因为Bitwarden的证书文件中缺少中间证书导致安卓系统的证书校验异常解决方式,生成带证书链的证......
  • CF1855B Longest Divisors Interval 题解
    原题链接:https://codeforces.com/contest/1855/problem/B题意:给定一个正整数n,找到满足该条件的区间[l,r]的长度的最大值:对于任意l<=i<=r,n均为i的倍数(多组数据)。思路:如果n是奇数,答案显然是1,因为任意两个连续的正整数一定会有一个2的倍数。将这一结论进行推广:......
  • CSS 浅探flex布局中使用的overflow ,及width/height=0
    关于overflow,w3school定义是:overflow:auto如果内容被修剪,则浏览器会显示滚动条以便查看其余的内容。我对于overflow:auto的初级理解是,设置父元素height/width,若子元素溢出,则自动显示纵向/横向滚动条。很长时间我是这么理解的,但是现在和flex布局一起就发现有点问题,在深入了解后......
  • Interop.Excel 个人总结二
    常用的有些是工作表操作,有些是excel操作,工作表操作备注为常用的excel命令1,excel操作为2,关闭等操作参考(Interop.Excel 个人总结一)Microsoft.Office.Interop.Excel.Applicationapp =newMicrosoft.Office.Interop.Excel.Application{Visible=true};//visble是是否展示exce......
  • 零代码编程:PDF文件名和Excel数据进行比对找不同
    F盘“北交所招股说明书”文件夹下有150个文件;F盘”北证A股20230703.xlsx”表格中证券名称有200多个;现在想找出文件夹下的哪些证券名称不在表格里面。在ChatGPT中输入提示词:写一段Python程序:F盘“北交所招股说明书”文件夹下有很多PDF文件,获取其标题名称,保存到列表:“已下载说明书的......
  • 零代码编程:用ChatGPT对Excel表格进行批量自动化处理
    F盘的“北交所上市公司全部发明专利”文件夹里面有几百个这样的Excel表格,格式一致,需要合并所有表格内容到一个表格,方便查找内容,但是不要前面两行。可以在ChatGPT中这样输入:写一段Python程序:F盘的“北交所上市公司全部发明专利”文件夹里面有很多xls格式表格,读取所有的表格文件;复制......
  • Python报错 | xlrd.biffh.XLRDError Excel xlsx file; not supported
    报错信息Python加载xlsx文件时,遇到:xlrd.biffh.XLRDErrorExcelxlsxfile;notsupported错误原因报错翻译过来是:xlrd.biffh.xlrd错误:Excelxlsx文件;不受支持解决方案方法1:安装指定低版本的xlrd,执行下面的pip安装命令即可:pipinstallxlrd==1.2.0方法2:Excel另存为......
  • Codeforces Round 889 (Div. 2) 题解
    \(6\)题只做出来\(1\)题,损失惨重A.DaltontheTeacher显然,答案一定和最初的不满意人数有关,所以输入的时候统计一下然后,将不满意的人的座位每两个人交换一次即可,交换次数就是答案如果不满意人数是奇数,那么答案还要加\(1\)时间复杂度\(O(n)\)(输入的复杂度)B.LongestD......
  • 【题解】[ABC312G] Avoid Straight Line(容斥,树上统计,dfs)
    【题解】[ABC312G]AvoidStraightLine题目链接[ABC312G]AvoidStraightLine题意概述给定一棵\(n\)个节点的树,第\(i\)条边连接节点\(a_i\)和\(b_i\),要求找到满足以下条件的三元整数组\((i,j,k)\)的数量:\(1\lei<j<k\len\);对于树上任意一条简单路径,都不同时经......