蓝桥杯备赛练习1

[蓝桥杯 2023 省 B] 冶炼金属

题目描述

小蓝有一个神奇的炉子用于将普通金属 O 冶炼成为一种特殊金属 X。这个炉子有一个称作转换率的属性 V V V V V V 是一个正整数,这意味着消耗 V V V 个普通金属 O 恰好可以冶炼出一个特殊金属 X,当普通金属 O 的数目不足 V V V 时,无法继续冶炼。

现在给出了 N N N 条冶炼记录,每条记录中包含两个整数 A A A B B B,这表示本次投入了 A A A 个普通金属 O,最终冶炼出了 B B B 个特殊金属 X。每条记录都是独立的,这意味着上一次没消耗完的普通金属 O 不会累加到下一次的冶炼当中。

根据这 N N N 条冶炼记录,请你推测出转换率 V V V 的最小值和最大值分别可能是多少,题目保证评测数据不存在无解的情况。

输入格式

第一行一个整数 N N N,表示冶炼记录的数目。

接下来输入 N N N 行,每行两个整数 A , B A,B A,B,含义如题目所述。

输出格式

输出两个整数,分别表示 V V V 可能的最小值和最大值,中间用空格分开。

样例 #1

样例输入 #1

3
75 3
53 2
59 2

样例输出 #1

20 25

提示

【样例说明】

V = 20 V=20 V=20 时,有: ⌊ 75 20 ⌋ = 3 , ⌊ 53 20 ⌋ = 2 , ⌊ 59 20 ⌋ = 2 \left\lfloor\frac{75}{20}\right\rfloor=3,\left\lfloor\frac{53}{20}\right\rfloor=2,\left\lfloor\frac{59}{20}\right\rfloor=2 2075=3,2053=2,2059=2,可以看到符合所有冶炼记录。

V = 25 V=25 V=25 时,有: ⌊ 75 25 ⌋ = 3 , ⌊ 53 25 ⌋ = 2 , ⌊ 59 25 ⌋ = 2 \left\lfloor\frac{75}{25}\right\rfloor=3,\left\lfloor\frac{53}{25}\right\rfloor=2,\left\lfloor\frac{59}{25}\right\rfloor=2 2575=3,2553=2,2559=2,可以看到符合所有冶炼记录。

且再也找不到比 20 20 20 更小或者比 25 25 25 更大的符合条件的 V V V 值了。

【评测用例规模与约定】

对于 30 % 30 \% 30% 的评测用例, 1 ≤ N ≤ 1 0 2 1 \leq N \leq 10^{2} 1N102

对于 60 % 60 \% 60% 的评测用例, 1 ≤ N ≤ 1 0 3 1 \leq N \leq 10^{3} 1N103

对于 100 % 100 \% 100% 的评测用例, 1 ≤ N ≤ 1 0 4 1 \leq N \leq 10^{4} 1N104 1 ≤ B ≤ A ≤ 1 0 9 1 \leq B \leq A \leq 10^{9} 1BA109

蓝桥杯 2023 省赛 B 组 C 题。

思路:对于每一组(a,b),都有使条件成立的最大值和最小值,求交集, 即求最大值的最小值,求最小值的最大值,数学题

AC Code

#include <bits/stdc++.h>
#include <vector>
#define ll long long
#define int long long
#define pii pair<int, int>
#define pb push_back
#define gcd __gcd
#define lcm(a, b) (a * b) / gcd(a, b)
#define all(a) a.begin(), a.end()
#define mem(a, x) memset(a, x, sizeof(a))
#define f(i, s, e) for (int i = s; i <= e; i++)
#define ff(i, s, e) for (int i = s; i >= e; i--)
#define setbits(x) __builtin_popcount(x)
#define zrobits(x) __builtin_ctzll(x)
#define mod 100000007
#define maxn (ll)(2e5 + 5000)
#define INF 0x3f3f3f3f
using namespace std;
// set<int>::iterator it;
int n;
int a;
int b;
signed main(void)
{
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cin >> n;
    int ans1=INF,ans2=-1;
    f(i,0,n-1)
    {
        cin >> a>> b;
        ans1=min(ans1,a / b);
        ans2=max(ans2,a/(b+1)+1);//考虑造b+1,此时a/(b+1)刚好不满足条件,所以加一,就是最小值
    }
    cout << ans2 << " " << ans1 << endl;
    return 0;
}

[蓝桥杯 2023 省 B] 飞机降落

题目描述

N N N 架飞机准备降落到某个只有一条跑道的机场。其中第 i i i 架飞机在 T i T_{i} Ti 时刻到达机场上空,到达时它的剩余油料还可以继续盘旋 D i D_{i} Di 个单位时间,即它最早可以于 T i T_{i} Ti 时刻开始降落,最晩可以于 T i + D i T_{i}+D_{i} Ti+Di 时刻开始降落。降落过程需要 L i L_{i} Li 个单位时间。

一架飞机降落完毕时,另一架飞机可以立即在同一时刻开始降落,但是不能在前一架飞机完成降落前开始降落。

请你判断 N N N 架飞机是否可以全部安全降落。

输入格式

输入包含多组数据。

第一行包含一个整数 T T T,代表测试数据的组数。

对于每组数据,第一行包含一个整数 N N N

以下 N N N 行,每行包含三个整数 T i , D i , L i T_{i},D_{i},L_{i} Ti,Di,Li

输出格式

对于每组数据,输出 YES 或者 NO,代表是否可以全部安全降落。

样例 #1

样例输入 #1

2
3
0 100 10
10 10 10
0 2 20
3
0 10 20
10 10 20
20 10 20

样例输出 #1

YES
NO

提示

【样例说明】

对于第一组数据,可以安排第 3 架飞机于 0 时刻开始降落,20 时刻完成降落。安排第 2 架飞机于 20 时刻开始降落,30 时刻完成降落。安排第 1 架飞机于 30 时刻开始降落,40 时刻完成降落。

对于第二组数据,无论如何安排,都会有飞机不能及时降落。

【评测用例规模与约定】

对于 30 % 30 \% 30% 的数据, N ≤ 2 N \leq 2 N2

对于 100 % 100 \% 100% 的数据, 1 ≤ T ≤ 10 1 \leq T \leq 10 1T10 1 ≤ N ≤ 10 1 \leq N \leq 10 1N10 0 ≤ T i , D i , L i ≤ 1 0 5 0 \leq T_{i},D_{i},L_{i} \leq 10^{5} 0Ti,Di,Li105

蓝桥杯 2023 省赛 B 组 D 题。

思路:DFS,直接暴搜,dp尼姆,沙沟才dp

AC Code

#include <bits/stdc++.h>
#define ll long long
#define int long long
#define pii pair<int, int>
#define pb push_back
#define gcd __gcd
#define lcm(a, b) (a * b) / gcd(a, b)
#define all(a) a.begin(), a.end()
#define mem(a, x) memset(a, x, sizeof(a))
#define f(i, s, e) for (int i = s; i <= e; i++)
#define ff(i, s, e) for (int i = s; i >= e; i--)
#define setbits(x) __builtin_popcount(x)
#define zrobits(x) __builtin_ctzll(x)
#define mod 100000007
#define maxn (ll)(2e5 + 5000)
#define INF 0x3f3f3f3f
using namespace std;
// set<int>::iterator it;
int n;
int flag = 0;
struct temp
{
    int l, r, t; // 最早降落,最迟降落,降落时间
};
struct temp a[maxn];
bool vis[maxn] = {false};
void dfs(int ti, int cnt) // 现在的时间,降落的飞机数量
{
    if (cnt == n)
    {
        flag = 1;
        return;
    }
    f(i, 1, n)
    {
        if (!vis[i] && a[i].r >= ti)
        {
            vis[i] = true;
            if (a[i].l >= ti) // 最早降落时间大于等于现在时间
            {
                dfs(a[i].l + a[i].t, cnt + 1);
            }
            else
            {
                dfs(ti + a[i].t, cnt + 1);
            }
            vis[i] = false;
        }
    }
    return;
}
void solve()
{
    flag = 0;
    cin >> n;
    f(i, 1, n)
    {
        cin >> a[i].l >> a[i].r >> a[i].t;
        a[i].r += a[i].l;
    }
    dfs(0,0);
    if (flag == 0)
    {
        cout << "NO" << endl;
    }
    else
    {
        cout << "YES" << endl;
    }
    return;
}
signed main(void)
{
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
    return 0;
}

[蓝桥杯 2023 省 B] 接龙数列

题目描述

对于一个长度为 K K K 的整数数列: A 1 , A 2 , … , A K A_{1},A_{2},\ldots,A_{K} A1,A2,,AK,我们称之为接龙数列当且仅当 A i A_{i} Ai 的首位数字恰好等于 A i − 1 A_{i-1} Ai1 的末位数字( 2 ≤ i ≤ K 2 \leq i \leq K 2iK)。

例如 12 , 23 , 35 , 56 , 61 , 11 12,23,35,56,61,11 12,23,35,56,61,11 是接龙数列; 12 , 23 , 34 , 56 12,23,34,56 12,23,34,56 不是接龙数列,因为 56 56 56 的首位数字不等于 34 34 34 的末位数字。所有长度为 1 1 1 的整数数列都是接龙数列。

现在给定一个长度为 N N N 的数列 A 1 , A 2 , … , A N A_{1},A_{2},\ldots,A_{N} A1,A2,,AN,请你计算最少从中删除多少 个数,可以使剩下的序列是接龙序列?

输入格式

第一行包含一个整数 N N N

第二行包含 N N N 个整数 A 1 , A 2 , … , A N A_{1},A_{2},\ldots,A_{N} A1,A2,,AN

输出格式

一个整数代表答案。

样例 #1

样例输入 #1

5
11 121 22 12 2023

样例输出 #1

1

提示

【样例说明】

删除 22 22 22,剩余 11 , 121 , 12 , 2023 11,121,12,2023 11,121,12,2023 是接龙数列。

【评测用例规模与约定】

对于 20 % 20 \% 20% 的数据, 1 ≤ N ≤ 20 1 \leq N \leq 20 1N20

对于 50 % 50 \% 50% 的数据, 1 ≤ N ≤ 1 0 4 1 \leq N \leq 10^4 1N104

对于 100 % 100 \% 100% 的数据, 1 ≤ N ≤ 1 0 5 1 \leq N \leq 10^{5} 1N105 1 ≤ A i ≤ 1 0 9 1 \leq A_{i} \leq 10^{9} 1Ai109。所有 A i A_{i} Ai 保证不包含前导 0。

蓝桥杯 2023 省赛 B 组 E 题。

思路:线性dp,状态有点难想,不过只要设计出了状态,转移方程很好想

AC Code

#include <algorithm>
#include <bits/stdc++.h>
#define ll long long
#define int long long
#define pii pair<int, int>
#define pb push_back
#define gcd __gcd
#define lcm(a, b) (a * b) / gcd(a, b)
#define all(a) a.begin(), a.end()
#define mem(a, x) memset(a, x, sizeof(a))
#define f(i, s, e) for (int i = s; i <= e; i++)
#define ff(i, s, e) for (int i = s; i >= e; i--)
#define setbits(x) __builtin_popcount(x)
#define zrobits(x) __builtin_ctzll(x)
#define mod 100000007
#define maxn (ll)(2e5 + 5000)
#define INF 0x3f3f3f3f
using namespace std;
// dp[i]代表以i结尾的最长接龙序列
int n;
string s[maxn];
int dp[20] = {0};
void solve()
{
    cin >> n;
    f(i, 1, n)
    {
        cin >> s[i];
    }
    f(i, 1, n)
    {
        dp[s[i][s[i].size() - 1] - '0'] = max(dp[s[i][s[i].size() - 1] - '0'], dp[s[i][0] - '0'] + 1);
    }
    cout << n - dp[max_element(dp, dp + 9) - dp] << endl;
}
signed main(void)
{
    ios::sync_with_stdio(false), cin.tie(nullptr);
    int t = 1;
    while (t--)
    {
        solve();
    }

    return 0;
}

[蓝桥杯 2023 省 A] 更小的数

题目描述

image

小蓝有一个长度均为 n n n 且仅由数字字符 0 ∼ 9 0 \sim 9 09 组成的字符串,下标从 0 0 0 n − 1 n-1 n1,你可以将其视作是一个具有 n n n 位的十进制数字 n u m num num,小蓝可以从 n u m num num 中选出一段连续的子串并将子串进行反转,最多反转一次。小蓝想要将选出的子串进行反转后再放入原位置处得到的新的数字 n u m n e w num_{new} numnew 满足条件 n u m n e w < n u m num_{new}<num numnew<num,请你帮他计算下一共有多少种不同的子串选择方案,只要两个子串在 n u m num num 中的位置不完全相同我们就视作是不同的方案。

注意,我们允许前导零的存在,即数字的最高位可以是 0 0 0,这是合法的。

输入格式

输入一行包含一个长度为 n n n 的字符串表示 n u m num num(仅包含数字字符 0 ∼ 9 0 \sim 9 09),从左至右下标依次为 0 ∼ n − 1 0 \sim n-1 0n1

输出格式

输出一行包含一个整数表示答案。

样例 #1

样例输入 #1

210102

样例输出 #1

8

提示

【样例说明】

一共有 8 8 8 种不同的方案:

  1. 所选择的子串下标为 0 ∼ 1 0\sim1 01,反转后的 n u m n e w = 120102 < 210102 num_{new} = 120102 < 210102 numnew=120102<210102
  2. 所选择的子串下标为 0 ∼ 2 0\sim2 02,反转后的 n u m n e w = 012102 < 210102 num_{new} = 012102 < 210102 numnew=012102<210102
  3. 所选择的子串下标为 0 ∼ 3 0\sim3 03,反转后的 n u m n e w = 101202 < 210102 num_{new} = 101202 < 210102 numnew=101202<210102
  4. 所选择的子串下标为 0 ∼ 4 0\sim4 04,反转后的 n u m n e w = 010122 < 210102 num_{new} = 010122 < 210102 numnew=010122<210102
  5. 所选择的子串下标为 0 ∼ 5 0\sim5 05,反转后的 n u m n e w = 201012 < 210102 num_{new} = 201012 < 210102 numnew=201012<210102
  6. 所选择的子串下标为 1 ∼ 2 1\sim2 12,反转后的 n u m n e w = 201102 < 210102 num_{new} = 201102 < 210102 numnew=201102<210102
  7. 所选择的子串下标为 1 ∼ 4 1\sim4 14,反转后的 n u m n e w = 201012 < 210102 num_{new} = 201012 < 210102 numnew=201012<210102
  8. 所选择的子串下标为 3 ∼ 4 3\sim4 34,反转后的 n u m n e w = 210012 < 210102 num_{new} = 210012 < 210102 numnew=210012<210102
【评测用例规模与约定】

对于 20 % 20\% 20% 的评测用例, 1 ≤ n ≤ 100 1 \le n \le 100 1n100

对于 40 % 40\% 40% 的评测用例, 1 ≤ n ≤ 1000 1 \le n \le 1000 1n1000

对于所有评测用例, 1 ≤ n ≤ 5000 1 \le n \le 5000 1n5000

思路:区间DP,没学过,被狠狠薄纱了,状态转移方程是 dp[i][j] = dp[i + 1][j - 1]。这意味着要计算 dp[i][j],我们需要知道 dp[i + 1][j - 1] 的值,这就决定了我们需要从后向前遍历字符串。确保了我们在计算一个状态时,所依赖的状态已经被计算过了。

优化的方法
基础知识

AC Code

#include <bits/stdc++.h>
#define ll long long
#define int long long
#define pii pair<int, int>
#define pb push_back
#define gcd __gcd
#define lcm(a, b) (a * b) / gcd(a, b)
#define all(a) a.begin(), a.end()
#define mem(a, x) memset(a, x, sizeof(a))
#define f(i, s, e) for (int i = s; i <= e; i++)
#define ff(i, s, e) for (int i = s; i >= e; i--)
#define setbits(x) __builtin_popcount(x)
#define zrobits(x) __builtin_ctzll(x)
#define mod 100000007
#define maxn (ll)(2e5 + 5000)
#define INF 0x3f3f3f3f
using namespace std;
// set<int>::iterator it;
string s;
int dp[5050][5050];
signed main(void)
{
    ios::sync_with_stdio(false), cin.tie(nullptr);
    cin >> s;
    int n = s.size();
    f(i, 0, n - 1)
    {
        if (s[i] > s[i + 1])
        {
            dp[i][i + 1] = 1;//区间DP,要给最小的区间初始化
        }
    }
    int ans = 0;
    ff(i, n-1, 0)
    {
        f(j, i, n - 1)// 找i后面的
        {
            if (s[i] > s[j])
            {
                dp[i][j] = 1;//可以就是1
            }
            else if (s[i] == s[j])
            {
                dp[i][j] = dp[i + 1][j - 1];//相等的话就看里面的,状态转移方程
            }
            if (dp[i][j] == 1)
            {
                ans++;
            }
        }
    }
    cout << ans << endl;
    return 0;
}

总结:感觉要将300元拱手相让了,呜呜呜呜

  • 25
    点赞
  • 22
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值