牛客xb月赛45题解

csdn小白是屏蔽词,醉了

A - 悬崖

题意

给定两墙之间的距离和每次跳跃的长度(注意不是高度),每次墙都要缩短1m,问跳跃长度为多少

注意跳不过去也是跳了

题解

判断一下跳不过去的情况,然后其他情况输出 n ∗ x n*x nx即可

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
ll n, x;

void solve(){
    cin >> x >> n;
    if(n <= x)
        cout << n * x;
    else
        cout << x;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
}

B - 数数

题意

给定一个dfs函数 ,问执行到第n层的时候ans为多少

题解

我们跑debug发现,每次答案都是为 n 2 n^2 n2所以直接输出就行了

当然,我们也能发现,答案本质上就是 1 + 3 + 5 + 7 … 1+3+5+7\dots 1+3+5+7,也就是 n 2 n^2 n2

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int ans;
ll n;

void dfs(int cnt, int num){//cnt从1开始 如同dfs(1)
    if(num == n + 1)
        return;
    for(int i=1;i<=cnt;i++)ans++;
    dfs(cnt+2, num + 1);
}


void solve(){
    cin >> n;
    cout << n * n;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
}

C - 山楂

题意

题意很简单,就不细说了

题解

首先肯定要尽可能的多合并,因为高一级的贡献肯定比低一级的贡献要高

我们假设这样一种情况,第i级上有4个,第i+1上有2个,那么如果第i级上选择4个进行合并,则会有 4 ∗ i 4*i 4i的贡献,如果是选择3个,则会有 3 ∗ i + 3 ∗ ( i + 1 ) = 6 ∗ i + 1 3*i+3*(i+1)=6*i+1 3i+3(i+1)=6i+1的贡献

我们模拟时候发现当一级的糖果数量大于5的时候,我们一定可以把当前的所有的糖果全部都用上,因为当大于6个的时候,每当多出来的就可以放在其他满足大于等于3的合法方案上

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Pb4D1KIy-1646653142661)(牛客小白月赛45.assets/image-20220307183001457.png)]

在x等于5的时候,就只能是看做4个了,这时候显然用4个是最优的

0,1,2显然不行,3只能用3个,4只能用4个

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int a[10];

void solve(){
    for (int i = 1; i <= 8; i++){
        cin >> a[i];
    }

    ll ans = 0;
    for (int i = 1; i <= 8; i++){
        ll num = a[i];
        if(a[i] < 3)
            num = 0;
        else if(num == 5)
            num = 4;
        a[i + 1] += num / 3;
        ans += num * i;
    }
    cout << ans;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
}

D - 切糕

题意

这题题意还算简单,我们知道,每一个合法的括号序列看做一个切糕,问能切多少个不同的切法

题解

本质上我们知道,要切多少次的话,对于每一个合法的序列都是可以是已经分出来的一个切糕,我们要切不同的切法,本质上就是对于每一个最小的切糕,我们需不需要把他切出来

也就是本质上就是对于每一个可切的点 ,我们切还是不切,所以说假设切点有x个,那么答案就是 2 x 2^x 2x

而切点的个数就是每个切糕的隔板,就是切糕数-1

因为很大,记得快速幂

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
string s;

long long ksm(long long a,long long b,long long p = mod) {long long ans=1;while (b) {if (b&1) ans=ans*a%p; a=a*a%p; b>>=1;} return ans;}

void solve(){
    cin >> s;
    int cnt = 0;
    int x = 0;
    for (int i = 0; i < s.size(); i++){
        if(s[i] == '(')
            x++;
        else{
            x--;
            if(x == 0){
                cnt++;
            }
            if(x < 0){
                cout << -1;
                return;
            }
        }
    }
    if(x != 0){
        cout << -1;
        return;
    }

    // cout << cnt << endl;

    cout << ksm(2, cnt - 1);
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
}

E - 筑巢

这个题赛后来看

真的就是树上的最大子段和问题

题解

我们定义状态为:dp[i]表示以i为根节点的,选择i号点的连通块的最大舒适度

这样的定义的目的是如果选择了这个点,我们每一个方案都不重不漏,我们还想知道每个数选或不选,那么我们最好的状态就是在状态上包含了这个点

那么状态转移方程就是: d p [ i ] = a [ i ] + ∑ j m a x ( 0 , d p [ j ] , w [ i − > j ] ) dp[i]=a[i]+\sum_jmax(0, dp[j],w[i->j]) dp[i]=a[i]+jmax(0,dp[j],w[i>j])

边界情况就是我们只选当前这个点,就是 d p [ i ] = a [ i ] dp[i]=a[i] dp[i]=a[i]

Code

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#include <map>
#include <vector>
#include <set>
#include <queue>
#include <stack>
#include <sstream>
#include <unordered_map>
#define ll long long
#define ull unsigned long long
#define re return
#define pb push_back
#define Endl "\n"
#define endl "\n"
#define x first
#define y second
#define all(x) (x).begin(),(x).end()

using namespace std;

typedef pair<int, int> PII;

const int N = 1e5 + 10;
const int M = 1e5 + 10;
const int mod = 1000000007;
const int INF = 0x3f3f3f3f;

int dx[4] = {-1,0,1,0};
int dy[4] = {0,1,0,-1};

int T;
int n;
int a[N];
vector<PII> g[N];
ll dp[N]; // 以i为根节点的,选择i号点的连通块的最大舒适度

void dfs(int u, int fa){
    dp[u] = a[u];
    for(auto [v, w] : g[u]){
        if(v == fa)
            continue;
        dfs(v, u);
        dp[u] = max(dp[u], dp[u] + dp[v] + w);
    }
}

void solve(){
    cin >> n;
    for (int i = 1; i <= n; i++){
        cin >> a[i];
    }

    for (int i = 1; i < n;i++){
        int x, y, w;
        cin >> x >> y >> w;
        g[x].pb({y, w});
        g[y].pb({x, w});
    }

    dfs(1, -1);
    ll ans = -1e9;
    for (int i = 1; i <= n; i++)
        ans = max(ans, dp[i]);
    cout << ans;
}

int main(){
    ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
    T = 1;
    // cin >> T;
    while(T--){
        solve();
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值