“蔚来杯“2022牛客暑期多校训练营6 题解

G题 Icon Design
思路:等比例输出图形即可。

#include<bits/stdc++.h>
using namespace std;
int n;
int main(){
    scanf("%d",&n);
    for(int i=1;i<=13*n+19;i++) cout<<'*';
    cout<<endl;
    for(int i=1;i<=n;i++){
        cout<<'*';
        for(int j=1;j<=13*n+17;j++) cout<<'.';
        cout<<'*';
        cout<<endl;
    }
    
    for(int i=1;i<=2*n+3;i++){
        cout<<'*';
        for(int j=1;j<=n+1;j++) cout<<'.';
        cout<<'@';
        for(int j=2;j<=2*n+2;j++){
            if(j==i) cout<<'@';
            else cout<<'.';
        }
        cout<<'@';
        for(int j=1;j<=n+1;j++) cout<<'.';
        cout<<'@';
        for(int j=1;j<=2*n+2;j++){
            if(i==1||i==n+2) cout<<'@';
            else cout<<'.';
        }
        for(int j=1;j<=n+1;j++) cout<<'.';
        cout<<'@';
        for(int j=1;j<=2*n+2;j++){
            if(i==2*n+3) cout<<'@';
            else cout<<'.';
        }
        for(int j=1;j<=n+1;j++) cout<<'.';
        if(i<=n+2||i==2*n+3) cout<<'@';
        else cout<<'.';
        
        for(int j=1;j<=2*n+1;j++){
            if(i==1||i==n+2||i==2*n+3) cout<<'@';
            else cout<<'.';
        }
        if(i==1||i>=n+2) cout<<'@';
        else cout<<'.';
        for(int j=1;j<=n+1;j++) cout<<'.';
        cout<<'*';
        cout<<endl;
    }
    
    for(int i=1;i<=n;i++){
        cout<<'*';
        for(int j=1;j<=13*n+17;j++) cout<<'.';
        cout<<'*';
        cout<<endl;
    }
    for(int i=1;i<=13*n+19;i++) cout<<'*';
    
}

J题 Number Game
思路:列出abc的变化公式然后找出规律,只有符合公式的情况才能够将c变化成x,其他情况都不行。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll t,a,b,c,x;
int main(){
    scanf("%lld",&t);
    while(t--){
    scanf("%lld%lld%lld%lld",&a,&b,&c,&x);
        if(a-2*b==0) {
            if(c==x||b-c==x) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
        else {
        ll d=(x%abs(a-2*b)+abs(a-2*b))%abs(a-2*b);
       c=(c%abs(a-2*b)+abs(a-2*b))%abs(a-2*b);
        ll y=((b-c)%abs(a-2*b)+abs(a-2*b))%abs(a-2*b);
            if(c==d||y==d) cout<<"Yes"<<endl;
            else cout<<"No"<<endl;
        }
    }
}

M题 Z-Game On the Grid
题意:爱丽丝和鲍勃正在玩一个n×m网格的游戏,其中每个单元格都有“A”、“B”或“.”写在上面。他们轮流在格子上移动棋子,爱丽丝先移动。最初,该棋子位于单元格(1,1)上。在每个玩家的回合中,他或她可以将棋子向右移动一格或向下移动一格。也就是说,如果该棋子在回合前位于单元格(x,y)上,玩家可以将其移动到(x+1,y)或(x,y+1),只要它不超出网格。在任何时候,如果棋子在有“A”的单元格上,爱丽丝赢,游戏结束。如果棋子在有“B”的单元格上,鲍勃获胜,游戏结束。如果棋子到达单元格(n,m)而游戏没有结束,那么它是一个平局。问Alice是否有必胜策略。
思路:博弈DP,博弈状态就是fij,代表走到这先手是否总有一种方法让他赢,平或输,思考第一种让他赢得方式,边界就是走到A的地方就必定有,走到B的地方就必定没有,走到(n,m)也必定没有,其他时候如果Alice走,向右或向下有只要有一个地方有必赢方案,这里的状态也为有必赢方案,若Bob走,只有当向下和向右走都有必赢方案是此状态才有必赢方案。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=510;
int f[N][N];
char s[N][N];
int n,m;
int dfs1(int x,int y){
    if(f[x][y]!=-1)return f[x][y];
    if(s[x][y]=='B')return f[x][y]=0;
    if(s[x][y]=='A')return f[x][y]=1;
    if(x==n&&y==m)return f[x][y]=0;
    if((x+y)%2==0){
        if(x==n)return f[x][y]=dfs1(x,y+1);
        else if(y==m)return f[x][y]=dfs1(x+1,y);
        else return f[x][y]=(dfs1(x+1,y)||dfs1(x,y+1));
    }
    else{
        if(x==n)return f[x][y]=dfs1(x,y+1);
        else if(y==m)return f[x][y]=dfs1(x+1,y);
        else return f[x][y]=(dfs1(x+1,y)&&dfs1(x,y+1));
    }
}
int dfs2(int x,int y){
    if(f[x][y]!=-1)return f[x][y];
    if(s[x][y]=='B')return f[x][y]=0;
    if(s[x][y]=='A')return f[x][y]=0;
    if(x==n&&y==m)return f[x][y]=1;
    if((x+y)%2==0){
        if(x==n)return f[x][y]=dfs2(x,y+1);
        else if(y==m)return f[x][y]=dfs2(x+1,y);
        else return f[x][y]=(dfs2(x+1,y)||dfs2(x,y+1));
    }
    else{
        if(x==n)return f[x][y]=dfs2(x,y+1);
        else if(y==m)return f[x][y]=dfs2(x+1,y);
        else return f[x][y]=(dfs2(x+1,y)&&dfs2(x,y+1));
    }
}
int dfs3(int x,int y){
    if(f[x][y]!=-1)return f[x][y];
    if(s[x][y]=='B')return f[x][y]=1;
    if(s[x][y]=='A')return f[x][y]=0;
    if(x==n&&y==m)return f[x][y]=0;
    if((x+y)%2==0){
        if(x==n)return f[x][y]=dfs3(x,y+1);
        else if(y==m)return f[x][y]=dfs3(x+1,y);
        else return f[x][y]=(dfs3(x+1,y)|dfs3(x,y+1));
    }
    else{
        if(x==n)return f[x][y]=dfs3(x,y+1);
        else if(y==m)return f[x][y]=dfs3(x+1,y);
        else return f[x][y]=(dfs3(x+1,y)&dfs3(x,y+1));
    }
}
int main(){
    int T;
    cin>>T;
    while(T--){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
        memset(f,-1,sizeof(f));
        dfs1(1,1);
        if(f[1][1]==1)cout<<"yes"<<' ';
        else cout<<"no"<<' ';
        memset(f,-1,sizeof(f));
        dfs2(1,1);
        if(f[1][1]==1)cout<<"yes"<<' ';
        else cout<<"no"<<' ';
        memset(f,-1,sizeof(f));
        dfs3(1,1);
        if(f[1][1]==1)cout<<"yes"<<' ';
        else cout<<"no"<<' ';
        puts("");
    }
    return 0;
}

B题 Eezie and Pie
思路:对于一个节点能够往其他点配送当且仅当那个节点的d[i]>=两个节点的距离,并且配送的节点深度>=当前节点。因此我们考虑每一个节点,有多少个节点能够配送到该节点。也就是从节点i向根方向找出一个长度为d[i]的链,这个链上的所有节点都可以往i节点送一个派。也就是树链上所有节点+1,最后统计所有节点上的值即可。首先暴力一点想到用树剖。对于区间操作,可以变成差分操作。起点位置+1,终点位置-1即可。最后用一遍dfs统计答案。对于找到终点位置,用倍增思想找<=depth[i] - d[i]的节点即可,注意边界。

#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;
#define int long long
const int N = 2e6 + 10 , M = 4e6 + 10;
int h[N], e[M], ne[M], idx;
int id[N], cnt, out[N];
int dep[N], sz[N], top[N], fa[N], son[N];
int n, m;
int d[N];
int fat[N][30];
int f[N],w[N];

void add(int a, int b)  // 添加一条边a->b
{
    e[idx] = b, ne[idx] = h[a], h[a] = idx ++ ;
}

void dfs1(int u, int father)
{
    dep[u] = dep[father] + 1;
    sz[u] = 1;
    fa[u] = father;
    for(int k = 1 ; k <= 25 ; k ++ )
        fat[u][k] = fat[fat[u][k - 1]][k - 1];
    for(int i = h[u]; ~i ; i = ne[i])
    {
        int j = e[i];
        if(j == father) continue;
        fat[j][0] = u;
        dfs1(j, u);
        sz[u] += sz[j];
        if(sz[son[u]] < sz[j]) son[u] = j;
    }
}

void dfs2(int u, int father)
{
    f[u] = w[u];
    for(int i = h[u]; ~i ; i = ne[i])
    {
        int j = e[i];
        if(j == father) continue;
        dfs2(j, u);
        f[u] += f[j];
    }
}

int lca(int u, int depth)
{
    for(int k = 25 ; k >= 0 ; k -- )
    {
        if(dep[fat[u][k]] >= depth) 
            u = fat[u][k];
    }
    return u;
}

signed main()
{
    ios::sync_with_stdio(0), cin.tie(0);
    cin >> n;
    memset(h, -1, sizeof h);
    for(int i = 1 ; i < n ; i ++ )
    {
        int a, b;
        cin >> a >> b;
        add(a, b), add(b, a);
    }
    dfs1(1, 0);
    for(int i = 1 ; i <= n ; i ++ ) cin >> d[i];

    for(int i = 1 ; i <= n ; i ++ )
    {
        int tar = dep[i] - d[i];
        tar = max(1ll, tar);
        int t = lca(i, tar);
        w[fa[t]] -- ;
        w[i] ++ ;
    }
    dfs2(1, 0);
    for(int i = 1 ; i <= n ; i ++ )
        cout << f[i] << ' ';
    cout << endl;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值