AtCoder Regular Contest 170 A~D

2024-01-24 11:28
文章标签 atcoder contest 170 regular

本文主要是介绍AtCoder Regular Contest 170 A~D,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

A.Yet Another AB Problem(贪心)

题意:

给定两个字符串 S S S T T T,可以对 S S S进行如下操作:选择两个字符,将前面的改为 A A A,后面的改为 B B B,询问至少需要几次可以将 S S S变为 T T T,如果不能,输出 − 1 -1 1

分析:

分类讨论,如果 S i = A S_i=A Si=A T i = B T_i=B Ti=B,在 T T T字符串中 i i i位置前一定要有 T j = A T_j=A Tj=A,否则无法修改。如果 S i = B S_i=B Si=B T i = A T_i=A Ti=A,在 T T T字符串中 i i i位置后一定要有 T j = B T_j=B Tj=B,否则无法修改,如果 S S S之后存在 S j = A S_j=A Sj=A T j = B T_j=B Tj=B,可以做到一次修改完成两次对应。贪心进行修改即可。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
const int INF = 0x3f3f3f3f;
const int maxn = 2e5 + 5;
int sum[maxn];int main() {int n;string s, t;cin >> n >> s >> t;queue<int> q;for (int i = 0; i < n; i++) {if (t[i] == 'B' and s[i] == 'A')q.push(i);}for (int i = n - 1; i >= 0; i--) {if (t[i] == 'B')sum[i]++;if (i >= 1)sum[i - 1] = sum[i];}int num = 0, ans = 0, flag = 0;for (int i = 0; i < n; i++) {if (t[i] == 'A')num++;if (s[i] != t[i]) {if (s[i] == 'A') {if (!num) {cout << -1 << endl;flag = 1;break;}ans++;} else {if (!sum[i + 1]) {cout << -1 << endl;flag = 1;break;}ans++;while (!q.empty() && q.front() < i)q.pop();if (!q.empty()) {s[q.front()] = 'B';q.pop();}}}}if (!flag)cout << ans << endl;return 0;
}

B.Arithmetic Progression Subsequence(思维)

题意:

给出一个长度为 n n n的序列 a a a a i a_i ai 1 − 10 1-10 110的任意数字,一个区间 [ l , r ] [l,r] [l,r]被认为是好区间当且仅当满足以下条件:

  • 存在三元组 ( i , j , k ) (i,j,k) (i,j,k) ( l ≤ i < j < k ≤ r ) (l \le i < j< k \le r) (li<j<kr),满足 a j − a i = a k − a j a_j-a_i=a_k-a_j ajai=akaj

询问好区间的数量。

分析:

对于一个固定的左端点 i i i,如果 k k k越小,包含这个三元组的区间将会越多。遍历每一个 a i a_i ai,枚举 a j a_j aj的值,再通过差值找出符合条件的最小的 k k k k k k可以通过维护 n e x t 1 [ i ] [ j ] next1[i][j] next1[i][j] 即下标 j j j之后第一个数字 i i i的位置求得。将每一个 i i i所对应的最小 k k k存入 r i r_i ri,相加即可。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
const int N = 1e5 + 5;
int a[N], next1[13][N], r[N];
vector<int> pos[13];
vector<array<int, 3>> num;int main() {int n;cin >> n;for (int i = 1; i <= n; ++i) {cin >> a[i];pos[a[i]].push_back(i);}for (int d = 0; d <= 10; ++d) {for (int i = 1; i + 2 * d <= 10; ++i) {num.push_back({i, i + d, i + 2 * d});if (d)num.push_back({i + 2 * d, i + d, i});}}for (int i = 1; i <= 10; ++i) {next1[i][n + 1] = n + 1;for (int j = n; j >= 1; --j) {if (a[j + 1] == i)next1[i][j] = j + 1;elsenext1[i][j] = next1[i][j + 1];}}for (int i = 1; i <= n; ++i)r[i] = n + 1;for (auto &[x, y, z]: num) {for (auto p: pos[x]) {int id = p;id = next1[y][id];id = next1[z][id];if (id <= n)r[p] = min(r[p], id);}}for (int i = n - 1; i >= 1; --i)r[i] = min(r[i], r[i + 1]);LL ans = 0;for (int i = 1; i <= n; ++i)ans += n - r[i] + 1;cout << ans << endl;return 0;
}

C.Prefix Mex Sequence(dp)

题意:

给出一个长度为 n n n的序列 s s s s i = 0 s_i=0 si=0或者 s i = 1 s_i=1 si=1
询问满足以下条件的序列 a a a的数量:

  • 如果 s i = 1 , a i = m e x ( a 1 , a 2 … a i − 1 ) s_i=1,a_i=mex(a_1,a_2 \dots a_{i-1}) si=1,ai=mex(a1,a2ai1)
  • 如果 s i = 0 , a i ≠ m e x ( a 1 , a 2 … a i − 1 ) s_i=0,a_i \neq mex(a_1,a_2 \dots a_{i-1}) si=0,ai=mex(a1,a2ai1)

请将答案对 998244353 998244353 998244353取模。

分析:

f [ i ] [ j ] f[i][j] f[i][j]表示序列 a a a i − 1 i-1 i1个元素,一共使用了 j j j种不同元素的方案数。

  • s i = 1 : f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] s_i=1:f[i][j]=f[i-1][j-1] si=1:f[i][j]=f[i1][j1] 填入一个新的数字。

  • s i = 0 : s_i=0: si=0: 分两种情况:

    • 填入的这个数字在之前没有出现过,除去前缀 m e x mex mex不可以选,那么还剩下 ( m − j + 1 ) (m-j+1) (mj+1)种数字。 f [ i ] [ j ] = f [ i − 1 ] [ j − 1 ] × ( m − j + 1 ) f[i][j]=f[i-1][j-1] \times (m-j+1) f[i][j]=f[i1][j1]×(mj+1)
    • 填入的数字之前出现过, f [ i ] [ j ] = f [ i − 1 ] [ j ] × j f[i][j]=f[i-1][j] \times j f[i][j]=f[i1][j]×j

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
const int mod = 998244353;
const int N = 5e3 + 5;
int s[N];
LL f[N][N];int main() {int n, m;cin >> n >> m;for (int i = 1; i <= n; ++i)cin >> s[i];int k = min(n, m + 1);f[0][0] = 1;for (int i = 1; i <= n; ++i) {if (s[i]) {for (int j = 1; j <= k; ++j) {f[i][j] = f[i - 1][j - 1];}} else {for (int j = 0; j <= k; ++j) {if (j)f[i][j] = (f[i][j] + (m - j + 1) * f[i - 1][j - 1]) % mod;f[i][j] = (f[i][j] + j * f[i - 1][j]) % mod;}}}LL ans = 0;for (int i = 0; i <= k; ++i)ans = (ans + f[n][i]) % mod;cout << ans << endl;return 0;
}

D Triangle Card Game(博弈)

题意:

给出两个数组 A A A B B B,询问 B B B数组中是否存在一个数字使得无论从 A A A数组中取出哪两个数字都无法组成三角形,如果存在这样的数字,Bob获胜,否则Alice获胜。

分析:

先将 A A A B B B从大到小排序,设 A A A数组中取出的第一个数字为 x x x,第二个数字为 z z z B B B数组中取出的数字为 y y y

y < x y < x y<x时,组成三角形的条件为 y + z > x y+z>x y+z>x或者 x + y > z x+y>z x+y>z,对于Bob来说,选择最小的 y y y更不容易组成三角形。所以Bob会选择 b 1 b_1 b1

x ≤ y x \le y xy时,组成三角形的条件为 x + y > z x+y>z x+y>z或者 x + z > y x+z>y x+z>y,那么组不成三角形的条件变为 m i n ∣ y − z ∣ ≥ x min \vert y-z \vert \ge x minyzx,利用双指针进行维护。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
const int mod = 998244353;
const int N = 2e5 + 5;
int a[N], b[N], v[N];int main() {int t;cin >> t;while (t--) {int n;cin >> n;for (int i = 1; i <= n; i++)cin >> a[i];for (int i = 1; i <= n; i++)cin >> b[i];a[0] = -1e9, a[n + 1] = 2e9;for (int i = 0; i <= n; i++)v[i] = 1;sort(a + 1, a + 1 + n);sort(b + 1, b + 1 + n);for (int i = 1; i <= n; i++) {if (b[1] <= a[i]) {if (b[1] + a[i - 1] <= a[i] && b[1] + a[i] <= a[i + 1])v[i] = 0;}}int num = 0, ans = 0;for (int i = n, j = n; i; i--) {if (num >= a[i])v[i] = 0;while (j && b[j] >= a[i]) {if (a[i - 1] + a[i] <= b[j] && a[i] + b[j] <= a[i + 1])v[i] = 0;num = max(num, min(b[j] - a[i], a[i + 1] - b[j]));j--;}ans |= v[i];}if (ans)cout << "Alice" << endl;elsecout << "Bob" << endl;}return 0;
}

学习交流


以下为学习交流QQ群,群号: 546235402,每周题解完成后都会转发到群中,大家可以加群一起交流做题思路,分享做题技巧,欢迎大家的加入。

这篇关于AtCoder Regular Contest 170 A~D的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/639548

相关文章

2014 Multi-University Training Contest 8小记

1002 计算几何 最大的速度才可能拥有无限的面积。 最大的速度的点 求凸包, 凸包上的点( 注意不是端点 ) 才拥有无限的面积 注意 :  凸包上如果有重点则不满足。 另外最大的速度为0也不行的。 int cmp(double x){if(fabs(x) < 1e-8) return 0 ;if(x > 0) return 1 ;return -1 ;}struct poin

2014 Multi-University Training Contest 7小记

1003   数学 , 先暴力再解方程。 在b进制下是个2 , 3 位数的 大概是10000进制以上 。这部分解方程 2-10000 直接暴力 typedef long long LL ;LL n ;int ok(int b){LL m = n ;int c ;while(m){c = m % b ;if(c == 3 || c == 4 || c == 5 ||

2014 Multi-University Training Contest 6小记

1003  贪心 对于111...10....000 这样的序列,  a 为1的个数,b为0的个数,易得当 x= a / (a + b) 时 f最小。 讲串分成若干段  1..10..0   ,  1..10..0 ,  要满足x非递减 。  对于 xi > xi+1  这样的合并 即可。 const int maxn = 100008 ;struct Node{int

AtCoder Beginner Contest 370 Solution

A void solve() {int a, b;qr(a, b);if(a + b != 1) cout << "Invalid\n";else Yes(a);} B 模拟 void solve() {qr(n);int x = 1;FOR(i, n) FOR(j, i) qr(a[i][j]);FOR(i, n) x = x >= i ? a[x][i]: a[i][x];pr2(

leetcode#10. Regular Expression Matching

题目 Implement regular expression matching with support for ‘.’ and ‘*’. '.' Matches any single character.'*' Matches zero or more of the preceding element.The matching should cover the entire input

CF Bayan 2015 Contest Warm Up B.(dfs+暴力)

B. Strongly Connected City time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/probl

CF Bayan 2015 Contest Warm Up A.(模拟+预处理)

A. Bayan Bus time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output 题目链接: http://codeforces.com/contest/475/problem/A The fi

AtCoder Beginner Contest 369 D - Bonus EXP 动态规划

原题链接: https://atcoder.jp/contests/abc369/tasks/abc369_d 思路:   这道题为什么要用动态规划呢,其实,对于第i个怪物,我们有打与不打两种处理方式,而对于打,我们是获得两倍的经验值,还是一倍的经验值,与我们打了奇数只怪物还是打了偶数只怪物有关了,因此我们定义dp[i][0] 为前i只怪物总共打了偶数次,dp[i][1] 为前i只怪物总

2015 Multi-University Training Contest 5 1009 MZL#39;s Border

MZL's Border  Problem's Link:  http://acm.hdu.edu.cn/showproblem.php?pid=5351   Mean:  给出一个类似斐波那契数列的字符串序列,要你求给出的f[n]字符串中截取前m位的字符串s中s[1...i] = s[s.size()-i+1....s.size()]的最大长度。 analyse:   过计算

LeetCode - 10. Regular Expression Matching

10. Regular Expression Matching Problem's Link  ---------------------------------------------------------------------------- Mean:  给定一个串s和一个自动机p(模糊字符只含有'.'和'*'),问串s是否能够和自动机p匹配. analyse: