我是靠谱客的博主 激动冷风,这篇文章主要介绍LINE Verda Programming Contest (AtCoder Beginner Contest 263) A~E 题解A - Full HouseB - AncestorC - Monotonically IncreasingD - Left Right OperationE - Sugoroku 3,现在分享给大家,希望可以做个参考。

ABC263/LINE2022 A~E

  • [A - Full House](https://atcoder.jp/contests/abc263/tasks/abc263_a)
    • 题目大意
    • 输入格式
    • 输出格式
    • 样例
    • 分析
    • 代码
  • [B - Ancestor](https://atcoder.jp/contests/abc263/tasks/abc263_b)
    • 题目大意
    • 输入格式
    • 输出格式
    • 分析
    • 代码
  • [C - Monotonically Increasing](https://atcoder.jp/contests/abc263/tasks/abc263_c)
    • 题目大意
    • 输入格式
    • 输出格式
    • 分析
    • 代码
  • [D - Left Right Operation](https://atcoder.jp/contests/abc263/tasks/abc263_d)
    • 题目大意
    • 输入格式
    • 输出格式
    • 分析
    • 代码
  • [E - Sugoroku 3](https://atcoder.jp/contests/abc263/tasks/abc263_e)
    • 题目大意
    • 输入格式
    • 输出格式
    • 分析
    • 代码

A - Full House

题目大意

来自一个掼蛋爱好者的翻译qwq

给定一副扑克牌中五张牌的编号 A , B , C , D , E A,B,C,D,E A,B,C,D,E,判断这五张是否为一组“三带二”。(不懂的自行百度

数据范围: 1 ≤ A , B , C , D , E ≤ 13 1le A,B,C,D,Ele 13 1A,B,C,D,E13,且 A , B , C , D , E A,B,C,D,E A,B,C,D,E不会全部相同。

输入格式

A   B   C   D   E A~B~C~D~E A B C D E

输出格式

如果是“三带二”,输出Yes;否则,输出No

样例

A A A B B B C C C D D D E E E输出
1 1 1 2 2 2 1 1 1 2 2 2 1 1 1Yes
12 12 12 12 12 12 11 11 11 1 1 1 2 2 2No

分析

嘿嘿,被自己的翻译给笑喷了吓住了,从来没见过这么垃圾的翻译!
话不多说,这A题就是水(虽然studentWheat这位大佬还WA了3次,具体怎么WA的请大家好好学学引以为戒),解法很多,但是个人感觉还是直接统计一下来得简单明了,见代码。

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <cstdio> using namespace std; int cnt[13]; int main() { for(int i=0; i<5; i++) { int x; scanf("%d", &x); cnt[--x] ++; } bool has2 = false, has3 = false; for(int i=0; i<13; i++) if(cnt[i] == 2) has2 = true; else if(cnt[i] == 3) has3 = true; puts(has2 && has3? "Yes": "No"); return 0; }

B - Ancestor

题目大意

N N N个人,第 i i i个人的父/母是 P i P_i Pi,题目保证 P i < i P_i<i Pi<i
问:第 N N N个人是第 1 1 1个人的第几代?

2 ≤ N ≤ 50 2le Nle 50 2N50
1 ≤ P i < i 1le P_i<i 1Pi<i

输入格式

N N N
P 2   P 3   …   P N P_2~P_3~dots~P_N P2 P3  PN

输出格式

输出答案。

分析

本题可以使用 DFS text{DFS} DFS,但没有必要。题目限制条件特别给出了 P i < i P_i<i Pi<i,因此如果按输入顺序依次处理每个人的世代,一个人的父亲肯定在这个人之前被考察到。

下面来看详细过程。
我们设 depth i =   text{depth}_i=~ depthi=  i i i个节点的深度,因此答案为 depth N text{depth}_N depthN
初始时, depth 0 = 0 text{depth}_0=0 depth0=0。对于 i = 1 … N i=1dots N i=1N,依次设置 depth i : = depth P i + 1 text{depth}_i:=text{depth}_{P_i}+1 depthi:=depthPi+1
最终,输出结果即可。总时间复杂度为 O ( N ) mathcal O(N) O(N)

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <cstdio> #define maxn 55 using namespace std; int dep[maxn]; int main() { int n; scanf("%d", &n); for(int i=1; i<n; i++) { int f; scanf("%d", &f); dep[i] = dep[--f] + 1; } printf("%dn", dep[n - 1]); return 0; }

C - Monotonically Increasing

题目大意

输出所有的长度为 N N N严格上升的序列,其中每个元素都在 [ 1 , M ] [1,M] [1,M]之间,按字典升序输出, 1 ≤ N ≤ M ≤ 10 1le Nle Mle 10 1NM10

输入格式

N   M N~M N M

输出格式

字典升序输出所有符合条件的序列,一行一个,序列中的每个元素用空格分隔。

分析

基础的回溯算法题,见代码。

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#include <cstdio> #define maxn 15 using namespace std; int n, m, ans[maxn]; void dfs(int pos, int last) { if(pos == n) { for(int i=0; i<n; i++) printf("%d ", ans[i]); putchar('n'); return; } while(++last <= m) { ans[pos] = last; dfs(pos + 1, last); } } int main() { scanf("%d%d", &n, &m); dfs(0, 0); return 0; }

D - Left Right Operation

题目大意

给定长为 N N N的整数序列 A = ( A 1 , A 2 , … , A N ) A=(A_1,A_2,dots,A_N) A=(A1,A2,,AN)
你可以进行下列两个操作,每个最多一次:

  • 选择整数 x x x,将 A A A的前 x x x项全部改成 L L L
  • 选择整数 y y y,将 A A A的后 y y y项全部改成 R R R

求操作后,最小的 A A A中所有元素之和。

1 ≤ N ≤ 2 × 1 0 5 1le Nle 2times 10^5 1N2×105
− 1 0 9 ≤ L , R , A i ≤ 1 0 9 -10^9le L,R,A_ile 10^9 109L,R,Ai109

输入格式

N   L   R N~L~R N L R
A 1   A 2   …   A N A_1~A_2~dots~A_N A1 A2  AN

输出格式

输出答案。

分析

f i = ( f_i=( fi=(使用操作 1 1 1选择 x ≤ i xle i xi时的前 i i i个序列元素的最小和 ) ) )
     g i = ( ~~~~g_i=(     gi=(使用操作 2 2 2选择 y ≤ i yle i yi时的后 i i i个序列元素的最小和 ) ) )
则可得递推式 f i = min ⁡ { f i − 1 + A i , L × i } f_i=min{f_{i-1}+A_i,Ltimes i} fi=min{fi1+Ai,L×i} g i g_i gi同理。
此时,枚举两种操作的分界点 i i i,则答案为 min ⁡ i = 1 N ( f i + g N − i ) minlimits_{i=1}^N(f_i+g_{N-i}) i=1minN(fi+gNi)。实现时,可将 g g g数组倒过来计算,这样答案为 min ⁡ i = 1 N ( f i + g i + 1 ) minlimits_{i=1}^N(f_i+g_{i+1}) i=1minN(fi+gi+1)

递推式的正确性证明
前面已经提到了, f i = min ⁡ { f i − 1 + A i , L × i } f_i=min{f_{i-1}+A_i,Ltimes i} fi=min{fi1+Ai,L×i}为什么?
先看 min ⁡ min min后面的部分,应该好理解,就是前 i i i个全部替换成 L L L的总和。前面的 f i − 1 + A i f_{i-1}+A_i fi1+Ai才是关键。考虑 f i − 1 f_{i-1} fi1的计算来源,要么是从 f i − 2 + A i − 1 f_{i-2}+A_{i-1} fi2+Ai1递推过来的,要么也是直接用 L × ( i − 1 ) Ltimes(i-1) L×(i1)得到的。再考虑 f i − 2 , f i − 3 , … , f 1 f_{i-2},f_{i-3},dots,f_1 fi2,fi3,,f1会发现,递推式的结果一定是(一段 L L L)+(一段 A i A_i Ai)得到的。因此,这个递推式正确。 g g g的正确性也可以用同样的方法证明,感兴趣的读者可以自行尝试。

总时间复杂度为 O ( N ) mathcal O(N) O(N)

代码

注意使用long long

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
#include <cstdio> #define maxn 200005 using namespace std; using LL = long long; inline LL min(const LL& x, const LL& y) { return x < y? x: y; } int a[maxn]; LL f[maxn], g[maxn]; int main() { int n, l, r; scanf("%d%d%d", &n, &l, &r); for(int i=0; i<n; i++) scanf("%d", a + i); f[0] = min(l, a[0]); for(int i=1; i<n; i++) f[i] = min(f[i - 1] + a[i], (i + 1LL) * l); for(int i=n-1; i>=0; i--) g[i] = min(g[i + 1] + a[i], LL(n - i) * r); LL ans = g[0]; for(int i=0; i<n; i++) ans = min(ans, f[i] + g[i + 1]); printf("%lldn", ans); return 0; }

E - Sugoroku 3

题目大意

N N N个方格,分别是方格 1 1 1,方格 2 2 2,…,方格 N N N
在方格 1 , 2 , … , N − 1 1,2,dots,N-1 1,2,,N1上,各有一枚骰子。方格 i i i上的骰子会按照相同的概率随机输出 0 , 1 , … , A i 0,1,dots,A_i 0,1,,Ai中的一个。

直到到达方格 N N N之前,你每次会前进骰子输出的步数。换句话说,如果你在方格 x x x上( 1 ≤ x < N 1le x<N 1x<N),骰子输出了数字 y y y 0 ≤ y ≤ A i 0le yle A_i 0yAi),你下一步会到达方格 x + y x+y x+y

求到达方格 N N N步数的期望值,对 998244353 998244353 998244353取模。

2 ≤ N ≤ 2 × 1 0 5 2le Nle 2times 10^5 2N2×105
1 ≤ A i ≤ N − i 1le A_ile N-i 1AiNi 1 ≤ i < N 1le i<N 1i<N

有理数取模【洛谷模板:P2613】
任意一个有理数都可被表示为 P Q frac PQ QP的形式。令 R R R为取模的结果,则 R × Q ≡ P   (   m o d     998244353 ) Rtimes Qequiv P~(bmod~998244353) R×QP (mod 998244353)
友情提示:对于除法计算,如 A B frac AB BA计算时,改为 A × B P − 2   m o d   P Atimes B^{P-2}bmod P A×BP2modP,其他逐步取模即可。本题中, P = 998244353 P=998244353 P=998244353

输入格式

N N N
A 1   A 2   …   A N − 1 A_1~A_2~dots~A_{N-1} A1 A2  AN1

输出格式

输出答案,对 998244353 998244353 998244353取模。

分析

dp i =   text{dp}_i=~ dpi=  i i i N N N的期望步数,则初始状态为 dp N = 0 text{dp}_N=0 dpN=0,答案为 dp 1 text{dp}_1 dp1
由于在方格上不能倒退,因此考虑倒序计算 dp text{dp} dp。对于第 i i i个点,易得
dp i = ∑ j = i i + A i dp j A i + 1 + 1 text{dp}_i=frac{sumlimits_{j=i}^{i+A_i}text{dp}_j}{A_i+1}+1 dpi=Ai+1j=ii+Aidpj+1
其中,求和即遍历后面每一个下一步可能到达的位置,乘上出现概率 1 A i + 1 frac1{A_i+1} Ai+11,最后再加上 1 1 1表示使用一步。
由于左右都有 dp i text{dp}_i dpi,无法直接计算,我们将其单独提出并解方程,得:
dp i = ( ∑ j = i i + A i dp j ) + A i + 1 A i text{dp}_i=frac{(sumlimits_{j=i}^{i+A_i}text{dp}_j)+A_i+1}{A_i} dpi=Ai(j=ii+Aidpj)+Ai+1
此时,时间复杂度为 O ( N 2 log ⁡ P ) mathcal O(N^2log P) O(N2logP)(快速幂inv操作需要 log ⁡ P log P logP的时间,其中 P = 998244353 P=998244353 P=998244353),使用后缀和优化后可达 O ( N log ⁡ P ) mathcal O(Nlog P) O(NlogP),可以通过本题。

代码

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <cstdio> #define maxn 200005 #define MOD 998244353 using namespace std; using LL = long long; int a[maxn], suf[maxn]; inline int inv(LL x) { LL res = 1LL; int p = MOD - 2; while(p) { if(p & 1) (res *= x) %= MOD; (x *= x) %= MOD, p >>= 1; } return res; } int main() { int n, cur; scanf("%d", &n); for(int i=0; i<n-1; i++) scanf("%d", a + i); for(int i=n-2; i>=0; i--) { int t = suf[i + 1] - suf[i + 1 + a[i]]; if(t < 0) t += MOD; cur = (a[i] + t + 1LL) % MOD * inv(a[i]) % MOD; if((suf[i] = suf[i + 1] + cur) >= MOD) suf[i] -= MOD; } printf("%dn", cur); return 0; }

最后

以上就是激动冷风最近收集整理的关于LINE Verda Programming Contest (AtCoder Beginner Contest 263) A~E 题解A - Full HouseB - AncestorC - Monotonically IncreasingD - Left Right OperationE - Sugoroku 3的全部内容,更多相关LINE内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部