0%

2025牛客多校训练4(死胡同,交换变选数贪心)

Problem F. For the treasury!

把这个问题看成选K个数字,然后把这K个数字全部移到第一个位置,然后把多减的代价加回来。

Problem B. Blind Alley(看到这种砍掉一个方向,要想到dp)

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78442849&returnHomeType=1&uid=817445536

赛时提交有问题是因为并没有考虑这个动态的过程,或许这种题目还是要首先搞清楚这个模拟,把这个模拟的本质,模拟的策略给搞清楚。模拟的策略就是说,至少目前为止,我走到这个点,一定是可以到达

直接模拟这个玩家,其实通过题意理解,只要这个玩家所走到的点最终能够走到视野的尽头,那么这个玩家就认为他能够走到走到终点。

那么前面有一个反向bfs,得到所有我们能到达终点的点。(赛时解法中已经想到了)。

那么这个far数组,或者说dp数组,可以通过比较朴素的前缀dp得到。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
vector<vector<ll> > dp(N+5,vll(M+5));
ROF(j,M,1){
if(j==M){
FOR(i,1,N){
if(S[i][j]=='0'){
dp[i][j]=j;
}
}
continue;
}
FOR(i,1,N){
if(S[i][j]=='1') continue;
dp[i][j]=j;
dp[i][j]=max(dp[i][j+1],dp[i][j]);
}
FOR(i,2,N){
if(S[i][j]=='1') continue;
dp[i][j]=max(dp[i][j],dp[i-1][j]);
}
ROF(i,N-1,1){
if(S[i][j]=='1') continue;
dp[i][j]=max(dp[i][j],dp[i+1][j]);
}
}

然后模拟这个玩家。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
	while(!q.empty()){
auto [x,y]=q.front();q.pop();
FOR(i,0,2){
ll u=x+dxx[i],v=y+dyy[i];
if(u<1 || u>N) continue;
if(v<1 || v>M) continue;
if(vis2[u][v]) continue;
if(S[u][v]=='1') continue;
// 只要这个玩家所走到的点最终能够走到视野的尽头,那么这个玩家就认为他能够走到走到终点
if(dp[u][v]<y+K){ // 该玩家可以看到该点已经被堵死了。
continue;
}
if(!vis[u][v]){ // 如果按照前面的逻辑筛选过了,还是踏入了陷阱,输出yes
cout<<"Yes\n";
return;
}
vis2[u][v]=true;
q.EM(u,v);
}
}

https://ac.nowcoder.com/acm/contest/view-submission?submissionId=78459227

Problem I. I, Box

那么我个人认为难点在于这个题目需要输出推动序列,其实还是有点难的,难度在于这个模拟,以及代码实现上。

Problem G. Ghost in the Parentheses

首先,将( 转为1,)转为-1,始终有合法匹配(序列是合法的)就是前缀和始终为正。

通过该条件,我们能找出所有的不可交换位置(指的是你不能拿 和这个$( $ 换 )。

通过如下程序,可以计算出来这个 )所能选的右括号有rem=N/2fixrem=N/2-fix 个,但是这样之间计算概率只能通过第一个样例,那怎么办那?遇事不决,就上dp(当然我也不会,和grok学的,这个dp)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
	ll fix=0;
ll inv2=binpow(2,mod-2);
ll ans=0;
FOR(i,1,N){
if(A[i]==1 && Sum[i]<=1){
fix++;
}
if(A[i]==-1 && i!=N){
ll rem=N/2-fix;
#ifdef LOCAL
debug(rem);
#endif
ans+=1*inv2*(1-binpow(inv2,rem));
ans%=mod;
}
}
ans=1-ans;
ans%=mod;if(ans<0) ans+=mod;
cout<<ans<<"\n";