概述
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 1≤A,B,C,D,E≤13,且 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 1 | Yes |
12 12 12 | 12 12 12 | 11 11 11 | 1 1 1 | 2 2 2 | No |
分析
嘿嘿,被自己的翻译给笑喷了吓住了,从来没见过这么好垃圾的翻译!
话不多说,这A题就是水(虽然studentWheat这位大佬还WA了3次,具体怎么WA的请大家好好学学引以为戒),解法很多,但是个人感觉还是直接统计一下来得简单明了,见代码。
代码
#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
2≤N≤50
1
≤
P
i
<
i
1le P_i<i
1≤Pi<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=1…N,依次设置
depth
i
:
=
depth
P
i
+
1
text{depth}_i:=text{depth}_{P_i}+1
depthi:=depthPi+1。
最终,输出结果即可。总时间复杂度为
O
(
N
)
mathcal O(N)
O(N)。
代码
#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 1≤N≤M≤10。
输入格式
N M N~M N M
输出格式
按字典升序输出所有符合条件的序列,一行一个,序列中的每个元素用空格分隔。
分析
基础的回溯算法题,见代码。
代码
#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
1≤N≤2×105
−
1
0
9
≤
L
,
R
,
A
i
≤
1
0
9
-10^9le L,R,A_ile 10^9
−109≤L,R,Ai≤109
输入格式
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
x≤i时的前
i
i
i个序列元素的最小和
)
)
),
g
i
=
(
~~~~g_i=(
gi=(使用操作
2
2
2选择
y
≤
i
yle i
y≤i时的后
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{fi−1+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+gN−i)。实现时,可将
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{fi−1+Ai,L×i}。为什么?
先看 min min min后面的部分,应该好理解,就是前 i i i个全部替换成 L L L的总和。前面的 f i − 1 + A i f_{i-1}+A_i fi−1+Ai才是关键。考虑 f i − 1 f_{i-1} fi−1的计算来源,要么是从 f i − 2 + A i − 1 f_{i-2}+A_{i-1} fi−2+Ai−1递推过来的,要么也是直接用 L × ( i − 1 ) Ltimes(i-1) L×(i−1)得到的。再考虑 f i − 2 , f i − 3 , … , f 1 f_{i-2},f_{i-3},dots,f_1 fi−2,fi−3,…,f1会发现,递推式的结果一定是(一段 L L L)+(一段 A i A_i Ai)得到的。因此,这个递推式正确。 g g g的正确性也可以用同样的方法证明,感兴趣的读者可以自行尝试。
总时间复杂度为 O ( N ) mathcal O(N) O(N)。
代码
注意使用long long
。
#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,…,N−1上,各有一枚骰子。方格
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 1≤x<N),骰子输出了数字 y y y( 0 ≤ y ≤ A i 0le yle A_i 0≤y≤Ai),你下一步会到达方格 x + y x+y x+y。
求到达方格 N N N步数的期望值,对 998244353 998244353 998244353取模。
2
≤
N
≤
2
×
1
0
5
2le Nle 2times 10^5
2≤N≤2×105
1
≤
A
i
≤
N
−
i
1le A_ile N-i
1≤Ai≤N−i(
1
≤
i
<
N
1le i<N
1≤i<N)
有理数取模【洛谷模板:P2613】
任意一个有理数都可被表示为 P Q frac PQ QP的形式。令 R R R为取模的结果,则 R × Q ≡ P ( m o d 998244353 ) Rtimes Qequiv P~(bmod~998244353) R×Q≡P (mod 998244353)。
友情提示:对于除法计算,如 A B frac AB BA计算时,改为 A × B P − 2 m o d P Atimes B^{P-2}bmod P A×BP−2modP,其他逐步取模即可。本题中, 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 … AN−1
输出格式
输出答案,对 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=i∑i+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=i∑i+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),可以通过本题。
代码
#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 Verda Programming Contest (AtCoder Beginner Contest 263) A~E 题解A - Full HouseB - AncestorC - Monotonically IncreasingD - Left Right OperationE - Sugoroku 3所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复