AtCoder Regular Contest 173 A~D

2024-03-19 17:28
文章标签 atcoder contest 173 regular

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

A.Neq Number(数位 dp+二分)

题意:

正整数 X X X 如果满足以下条件,则称 N e q Neq Neq 数:

  • X X X 用十进制符号书写时,没有两个相邻的字符是相同的。

例如, 1 1 1 173 173 173 9090 9090 9090 N e q Neq Neq 数,而 22 22 22 6335 6335 6335 不是。

给你一个正整数 K K K 。求 第 K K K小的 N e q Neq Neq数。

分析:

考虑计算小于等于 k k k N e q Neq Neq数有多少个,利用二分枚举 m i d mid mid,用数位 d p dp dp计算小于等于 m i d mid mid N e q Neq Neq数有多少个,判断条件为相邻两位不同。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
LL dp[20][15], a[15];LL dfs(int pos, int pre, bool limit, bool flag) {if (pos == 0)return 1;if (!limit && !flag && dp[pos][pre] != -1)return dp[pos][pre];LL mx = 9, ans = 0;if (limit)mx = a[pos];for (int i = 0; i <= mx; i++) {if (!flag && i == pre)continue;ans += dfs(pos - 1, i, limit & (i == mx), flag && (i == 0));}if (!limit && !flag)dp[pos][pre] = ans;return ans;
}LL get(LL x) {LL tot = 0;while (x)a[++tot] = x % 10, x /= 10;return dfs(tot, 0, 1, 1);
}int main() {memset(dp, -1, sizeof(dp));LL t;cin >> t;while (t--) {LL x;cin >> x;LL l = 0, r = 1e18, mid, ans;while (l <= r) {mid = (l + r) / 2;if (get(mid) <= x)ans = mid, l = mid + 1;elser = mid - 1;}cout << ans + 1 << endl;}return 0;
}

B.Make Many Triangles(数学)

题意:

在一个二维平面上有 N N N 个不同的点。第 i i i 个点的坐标是 ( x i , y i ) (x_i,y_i) (xi,yi)
以这些点为顶点创建尽可能多的(非退化)三角形。在这里,同一个点不能作为多个三角形的顶点。求最多可创建的三角形个数。
非退化三角形是指三个顶点不相交的三角形。

分析:

l l l为平面上穿过点数最多的直线, 其上点数为 m m m:

  • m ≥ n − ⌊ n 3 ⌋ + 1 m \ge n - \lfloor \frac{n}{3} \rfloor +1 mn3n+1,答案为 n − m n-m nm,每从 l l l外取一个点,再从 l l l上选择两个点构成一个三角形。
  • m ≤ n − ⌊ n 3 ⌋ m \le n - \lfloor \frac{n}{3}\rfloor mn3n,答案可以取到上界 ⌊ n 3 ⌋ \lfloor \frac{n}{3} \rfloor 3n

求出平面上穿过点数最多的直线上点的个数,二者取小即可。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
LL n, tmp, x[305], y[305];bool check(LL ax, LL ay, LL bx, LL by, LL cx, LL cy) {return (bx - ax) * (cy - by) == (by - ay) * (cx - bx);
}int main() {cin >> n;for (int i = 1; i <= n; i++)cin >> x[i] >> y[i];for (int i = 1; i < n; i++) {for (int j = i + 1; j <= n; j++) {LL cnt = 2;for (int k = 1; k <= n; k++) {if (k == i || k == j)continue;if (check(x[i], y[i], x[j], y[j], x[k], y[k]))cnt++;}tmp = max(tmp, cnt);}}cout << min(n / 3, n - tmp) << endl;return 0;
}

C.Not Median(思维)

题意:

给你一个从 1 1 1 n n n 的整数排列 P = ( P 1 , P 2 , … , P N ) P=(P_1,P_2,\dots,P_N) P=(P1,P2,,PN)

对于每个 i = 1 , 2 , … , N i=1,2,\dots,N i=1,2,,N ,输出满足以下所有条件的一对整数 ( l , r ) (l,r) (l,r) r − l + 1 r-l+1 rl+1 的最小值。如果不存在这样的 ( l , r ) (l,r) (l,r) ,则输出-1

  • 1 ≤ l ≤ i ≤ r ≤ N 1 \leq l \leq i \leq r \leq N 1lirN
  • r − l + 1 r-l+1 rl+1 是奇数。
  • P P P 的连续子序列 ( P l , P l + 1 , … , P r ) (P_l,P_{l+1},\dots,P_r) (Pl,Pl+1,,Pr) 的中位数不是 P i P_i Pi

这里,长度为 L L L (奇数)的整数序列 A A A 的 中位数定义为将 A A A 按升序排序后得到的序列 A ′ A' A L + 1 2 \frac{L+1}{2} 2L+1 /之值。

分析:

我们假设 a n s i ans_i ansi表示 i i i位置的答案,因为 p p p是一个排列,同时区间长度为奇数,所以有且仅有一个位置是该区间的中位数。所以满足 a n s i > k ans_i > k ansi>k i i i的个数不超过 ⌈ n k ⌉ \lceil \frac{n}{k} \rceil kn。考虑从小到大枚举区间长度 k k k,每次对还未确定答案的位置判断是否存在长度为 k k k的合法区间。用 1 1 1表示大于 p i p_i pi的元素, − 1 -1 1表示小于 p i p_i pi的元素, 0 0 0表示 p i p_i pi,为了使得 p i p_i pi成为中位数,区间内的和要为 0 0 0。通过找规律发现,假定 i i i 左右两侧都有足够多的元素,那么对任意奇数 k k k仅有两种情况能够满足 a n s i > k ans_i > k ansi>k。所以每次判断只需要在前面的基础上判断常数种情况即可。上述规律不包括边界 1 1 1 n n n,所以要对 1 1 1 n n n单独进行处理。

代码:

#include <bits/stdc++.h>using namespace std;
typedef long long LL;
const int N = 5e5 + 5;
LL n, a[N], sum[N], i, k;
vector<LL> tmp1, tmp2;int main() {cin >> n;for (i = 1; i <= n; i++)cin >> a[i];for (i = 1; i <= n; i++) {if (i > 2 && ((a[i - 2] < a[i]) == (a[i - 1] < a[i])))sum[i] = 3;else if (i > 1 && i < n && ((a[i - 1] < a[i]) == (a[i + 1] < a[i])))sum[i] = 3;else if (i < n - 1 && ((a[i + 1] < a[i]) == (a[i + 2] < a[i])))sum[i] = 3;elsetmp2.push_back(i);}for (k = 5; k <= n; k += 2) {tmp1 = tmp2;tmp2.clear();for (auto i: tmp1) {if (i - k + 2 > 0 && i < n && (a[i - k + 2] < a[i]) != (a[i - 1] < a[i]))sum[i] = k;else if (i - k + 1 > 0 && (a[i - k + 1] < a[i]) == (a[i - k + 2] < a[i]))sum[i] = k;else if (i + k - 2 <= n && i > 1 && (a[i + k - 2] < a[i]) != (a[i + 1] < a[i]))sum[i] = k;else if (i + k - 1 <= n && (a[i + k - 1] < a[i]) == (a[i + k - 2] < a[i]))sum[i] = k;elsetmp2.push_back(i);}}for (auto i: tmp2)sum[i] = -1;for (i = 1; i <= n; i++)cout << sum[i] << ' ';return 0;
}

D.Bracket Walk (图论)

题意:

给你一个有向图 G G G ,其中有 N N N 个顶点和 M M M 条边。顶点的编号从 1 1 1 N N N ,每条边都标有 ()。第 i i i 条边是从顶点 u i u_i ui 指向顶点 v i v_i vi ,标签为 c i c_i ci 。该图不包含多条边或自循环。

在这个图中,对于任意两个顶点 s s s t t t ,都有一条从 s s s t t t 的路径。

请判断在图 G G G 中是否存在满足以下所有条件的路径

  • 路径的起点和终点顶点相同。
  • 对于 i = 1 , 2 , … , M i=1,2,\dots,M i=1,2,,M i i i 条 边在路径过程中至少使用了一次。
  • 将路径中使用的边的标签按照使用顺序排列得到的字符串是一个正则括号序列。

正则括号序列是满足以下条件之一的字符串:

  • 空字符串。
  • 它是由(正则括号序列 A A A)依次连接得到的字符串。
  • 是由两个非空的正则括号序列 A A A B B B 依次连接得到的字符串。

分析:

如果存在一条 () 出现次数相等的路径,那么必然可以通过更换路径起点来将形成的字符串循环移位为一个合法括号序列。因此答案路径是否存在等同于这样的路径是否存在。
有向图中的一条回路可以视作若干个环的组合。想要构造一条符合要求回路,我们可以先对于每条边求出一个包含它的环,再通过多次经过或增加某个环来平衡 ( ) 的数量。
( 的出现次数严格大于 ) 的出现次数的环为 A A A 类环,) 的出现次数严格大于 ( 的出现次数的环为 B B B 类环。不难发现若 A A A B B B 类环同时存在,一定可以通过调整两种环的经过次数构造出一组合法解。
如果只出现一种环,那么合法解一定不存在。通过反证法证明:
假设存在一组合法解,取一个 A A A 类环 t m p tmp tmp,由于合法解中每条边至少出现一次,我们将 t m p tmp tmp 中的边从合法解中删除(若某条边出现多次则只删除一次),合法解中剩下的部分一定由若干环组成,且由于合法解中 () 出现次数相等,去掉 t m p tmp tmp) 的出现次数必然多于 (。结合其由若干环组成,推断出这些环中至少存在一个 B B B 类环,与前提矛盾。
而如果两种环均未出现,可以任意构造合法解。
综上,只需要分别求出途中是否存在 A A A B B B类环。令( 边的边权为 − 1 −1 1) 边的边权为 1 1 1,通过 b e l l m a n − f o r d bellman-ford bellmanford求负环即可。

代码:

#include <bits/stdc++.h>using namespace std;
const int N = 5010;
const int M = 2 * N;
struct Edge {int x, y;char c;
} edge[M];
int f[N], g[N], save1[N];
int n, m;int solve(char c) {memset(f, 0, sizeof f);for (int t = 1; t <= n; t++) {memcpy(g, f, sizeof g);for (int j = 1; j <= m; j++)g[edge[j].y] = min(g[edge[j].y], g[edge[j].x] + ((edge[j].c == c) ? -1 : 1));swap(f, g);}for (int i = 1; i <= n; i++)save1[i] = f[i];for (int t = 1; t <= n; t++) {memcpy(g, f, sizeof g);for (int j = 1; j <= m; j++)g[edge[j].y] = min(g[edge[j].y], g[edge[j].x] + ((edge[j].c == c) ? -1 : 1));swap(f, g);}for (int i = 1; i <= n; i++)if (save1[i] != f[i])return true;return false;
}int main() {cin >> n >> m;for (int i = 1; i <= m; i++)cin >> edge[i].x >> edge[i].y >> edge[i].c;int f1 = solve('('), f2 = solve(')');if (f1 ^ f2)cout << "No" << endl;elsecout << "Yes" << endl;return 0;
}

赛后交流

在比赛结束后,会在交流群中给出比赛题解,同学们可以在赛后查看题解进行补题。

群号: 704572101,赛后大家可以一起交流做题思路,分享做题技巧,欢迎大家的加入。

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



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

相关文章

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: