首页 > 其他分享 >[ARC171] A~D 题解

[ARC171] A~D 题解

时间:2024-02-06 12:33:05浏览次数:40  
标签:int 题解 ARC171 long 2024 Moyou include mod

[ARC171] A~D 题解

A. No Attacking

最优策略是车隔行放,分讨一下就可以了。

if(n < a) cout << "No\n";
else {
    if(a * 2 < n) b -= (a + 1) * (n - a);
    else {
        b -= (n - a) * (n - a);
        if(b <= 0) cout << "Yes\n";
        else cout << "No\n";
        return ;
    }
    n -= a; 
    if(b <= 0) cout << "Yes\n";
    else if(b <= (n - a - 1) / 2 * n) cout << "Yes\n";
    else cout << "No\n";
}

B. Chmax

手玩一下发现排列之间有关系,往图论想,发现最终可以建出一张图,所有 \(a_i > i\) 的位置沿着图走一定会到达 \(a_i = i\) 的位置,并且只能走向下一个 \(a_j = a_i\) 的位置 \(j\),因为不能回头,而最后那些 \(a_i = i\) 的位置则可以指向所有还没有入度的位置,而每个没有入度的位置一定是一块的开头,于是记录一下到现在位置有多少个块的开头可以被选择,每次碰到一个终点位置算一下贡献即可。

坑点:如果 \(a_i < i\) 必不可能,如果 \(a_i\ne a_{a_i}\) 必不可能,因为你既然你可以到 \(a_i\),那你的 \(a\) 肯定至少有 \(a_{a_i}\),结合上一个条件就是不等号。

// Problem: B - Chmax
// Contest: AtCoder - AtCoder Regular Contest 171
// Author: Moyou
// Copyright (c) 2024 Moyou All rights reserved.
// Date: 2024-02-04 23:17:18

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
// #define int long long
using namespace std;
const int N = 2e5 + 10, mod = 998244353;

int n, a[N];
bool st[N], in[N], out[N];

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> n;
    for(int i = 1; i <= n; i ++) {
        cin >> a[i];
        if(!st[a[i]]) in[i] = 1, st[a[i]] = 1;
    }
    for(int i = 1; i <= n; i ++) {
        if(a[i] < i || (a[i] != a[a[i]])) {
            cout << 0 << '\n';
            return 0;
        }
    }
    memset(st, 0, sizeof st);
    for(int i = n; i; i --)
        if(!st[a[i]]) out[i] = 1, st[a[i]] = 1;
    int ans = 1;
    for(int i = 1, cnt = 0; i <= n; i ++) {
        cnt += in[i];
        if(out[i]) ans = 1ll * ans * cnt % mod, cnt --;
    }
    cout << ans << '\n';

    return 0;
}

C. Swap on Tree

两个操作序列得到的 \(a\) 相同当且仅当所有选择的边都一样,并且对于一个点,它四周的边选择的顺序也一样。

根据这个我们可以做一个 DP,用 \(f_{i, j, 0/1}\) 表示 \(i\) 的子树内,与 \(i\) 相连的边选择了 \(j\) 个,是否选择了父边的方案数。

\[f_{i, j, x} = f_{i, j, x}\times\sum_{k = 0}^{deg_v} f_{v, k, 0}+f_{i, j - 1, x}\times \sum_{k = 0}^{deg_v}f_{v, k, 1}\times j \]

树上背包类型的转移,分讨儿子边是否选择,如果选择就需要在前面 \(j - 1\) 条已选择的边里面确定一个顺序,所以要乘 \(j\),和式可以预处理。

时间复杂度:\(O(n^2)\)。

// Problem: [ARC171C] Swap on Tree
// Contest: Luogu
// Author: Moyou
// Copyright (c) 2024 Moyou All rights reserved.
// Date: 2024-02-06 11:24:52

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#define int long long
using namespace std;
const int N = 3e3 + 10, mod = 998244353;

int n, f[N][N][2], sz[N], s[N][2];
vector<int> g[N];
void dfs(int u, int fa) {
    sz[u] = 1, f[u][0][0] = 1, f[u][1][1] = (u > 1); // 注意根节点没有父边
    int d = g[u].size();
    for(auto v : g[u]) {
        if(v == fa) continue;
        dfs(v, u);
        sz[u] += sz[v];
        for(int j = d; j >= 0; j --)
            for(int x = 0; x < 2; x ++)
                f[u][j][x] = (f[u][j][x] * s[v][0] % mod + (j ? f[u][j - 1][x] * j % mod * s[v][1] % mod : 0)) % mod;
    }
    for(int j = 0; j <= d; j ++)
        for(int x = 0; x < 2; x ++)
            (s[u][x] += f[u][j][x]) %= mod;
}

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);
    }
    dfs(1, 1);
    cout << s[1][0] << '\n';

    return 0;
}

D. Rolling Hash

不妨把原式书写为:

\[\displaystyle \mathrm{hash}(X) = \left(\sum_{i=1}^n x_i B^{i}\right) \bmod P \]

由对称性可知这样是等价的。

这样一来,区间的哈希值就等于 \((h_r - h_{l - 1}) / {B^{r - l + 1}}\),这意味着题目中给定的若干条约束等价于 \(h_r\ne h_{l - 1}\)。

这种关系可以从图论的角度思考,建图之后我们需要解决这个子问题:

给定一张无向图,请判断是否存在一种染色方案使得所有相邻的点颜色不同,且颜色数 \(\le P\)。

这个是经典问题,可以用状压解决,具体而言,\(f_s\) 表示已经对 \(s\) 集合染色,最少颜色数,可以枚举子集,并且子集的点两两无边,转移。

时间复杂度:\(O(3^n)\)。

// Problem: D - Rolling Hash
// Contest: AtCoder - AtCoder Regular Contest 171
// Author: Moyou
// Copyright (c) 2024 Moyou All rights reserved.
// Date: 2024-02-05 22:08:52

#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
// #define int long long
using namespace std;
const int N = 17;

int n, m, p;
int b[N], f[(1 << N)], disj[(1 << N)];

signed main() {
    ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    cin >> p >> n >> n >> m;
    for(int i = 1, l, r; i <= m; i ++) {
        cin >> l >> r;
        b[l - 1] |= (1 << r), b[r] |= (1 << (l - 1));
    }
    n ++;
    for(int s = 0; s < (1 << n); s ++) {
        disj[s] = 1;
        for(int i = 0; i < n; i ++)
            if(s >> i & 1) if(s & b[i]) {
                disj[s] = 0;
                break;
            }
    }
    memset(f, 0x3f, sizeof f), f[0] = 0;
    for(int s = 0; s < (1 << n); s ++)
        for(int t = s; t; t = (t - 1) & s)
            if(disj[t]) f[s] = min(f[s], f[t ^ s] + 1);
    cout << (f[(1 << n) - 1] <= p ? "Yes" : "No") << '\n';

    return 0;
}

标签:int,题解,ARC171,long,2024,Moyou,include,mod
From: https://www.cnblogs.com/MoyouSayuki/p/18009529

相关文章

  • P3219 [HNOI2012] 三角形覆盖问题&P1222 三角形 题解
    严格单$\log$做法,附实现细节和代码。考虑从左往右扫描线,发现每次操作是线段上端点$-1$,插入线段,删除退化成点的线段。如果某时刻一条线段被另一条完全覆盖,那么这条线段显然不会产生贡献,可以删去。最后得到的线段一定是左端点单调递增时,右端点也单调递增,可以用set维护。当两......
  • P10145 [WC/CTS2024] 线段树 题解
    Link纪念一下场切题。题意:给定一棵(分点不一定为中点)的线段树,给定若干个询问区间,问有多少个线段树上结点的集合,知道了这些结点对应的区间和就可以知道任何一个询问区间的和。从询问区间开始考虑。会发现可以把所有\(a_i\)分成若干个集合,只要知道每个集合的和就可以知道所有询......
  • 浅谈甲类生产厂房应急照明和疏散指示系统的设计问题解析
    摘要:文章结合电气设计项目实践经验,分析了甲类生产厂房消防应急照明和疏散指示系统设计中照明灯和标志灯的设置、疏散走道和疏散通道的规划、集中控制型系统类型的选择、电压等级的选择中存在的问题,总结了相关经验,可以为同类工程提供参考。关键词:甲类生产厂房;消防应急照明和疏散指示......
  • 题解 CF1876B
    题意给定一个数组\([a_1,a_2,a_3.\cdots,a_n]\),一开始所有元素都为白色。你可以选定其中的至少一个元素涂成黑色,共有\(2^n-1\)种涂法。此时对于所有黑色元素\(a_i\),下标为\(i\)的倍数的所有白色元素都将变成绿色。此时数组中所有黑色和绿色元素的最大值记为此种涂法的......
  • 洛谷 P10145 [WC/CTS2024] 线段树 题解--zhengjun
    提供一种考场做法,在思路上和官方题解的差异蛮大的,虽然结果差不多。首先需要发现\([l,r)\)区间可以算出来的充要条件是:如果对于每个选中的节点\(u\),连无向边\((L_u,R_u)\),则当且仅当\(l\)和\(r\)连通时区间\([l,r)\)可以算出来。证明的话,用前缀和理解这些东西,分别考虑......
  • 题解 CF1849D
    萌新的第一篇题解题目大意对于一个初始颜色都为蓝色的数组\(a_1,a_2,\dots,a_n\)其中\(a_n\in\{0,1,2\}\),现在可以进行两个操作:花费\(1\)个金币,将\(a_i\)涂成红色;选择一个红色的\(a_i>0\),将\(a_{i-1}\)或\(a_{i+1}\)涂成红色,同时\(a_i\)减\(1\)。输出金......
  • F. 乘积最大(题解)
    题目今年是国际数学联盟确定的“2000——世界数学年”,又恰逢我国著名数学家华罗庚先生诞辰90周年。在华罗庚先生的家乡江苏金坛,组织了一场别开生面的数学智力竞赛的活动,你的一个好朋友XZ也有幸得以参加。活动中,主持人给所有参加活动的选手出了这样一道题目:设有一个长度为......
  • [ARC135D] Add to Square 题解
    题目链接点击打开链接题目解法很牛的题!!!先考虑一步很牛的转化:把矩阵黑白染色,且\(i+j\)为奇数的位置的值取反,每次操作变为左上右下\(+v\),左下右上\(-v\)这样有啥好处?操作不会使行和列的和改变考虑答案的下界显然是:\(\max\{\)行的绝对值之和,列的绝对值之和\(\}\)这里给出......
  • luogu2647题解
    首先这道题没有规定选几个。一开始我以为是全选,然后想了个贪心才发现看错了。那我们先来假设选\(m\)个。这个题的每个物品都会影响后面物品的收益,不好看。由于每个物品\(i\)对后选的其他物品减少的收益都是\(R_i\),因此我们在保证总价值不变的情况下转化一下,把该物品的价......
  • P10125 「Daily OI Round 3」Simple 题解
    题目传送门简单模拟,主要考察字符串。首先输入一个char类型的数组,然后直接遍历每一位是否为Acoipp或Svpoll即可。//Simple//codeby:cq_irritater//time:2024/02/04#include<bits/stdc++.h>usingnamespacestd;chara[10];intmain(){//freopen("c......