【传智杯】初赛部分题解

博客主页:@披星戴月的贾维斯
欢迎关注:点赞收藏留言
系列专栏: 蓝桥杯
请不要相信胜利就像山坡上的蒲公英一样唾手可得,但是请相信,世界上总有一些美好值得我们全力以赴,哪怕粉身碎骨!
一起加油,去追寻、去成为更好的自己!

文章目录

  • 前言
  • 1.P8825 [传智杯 #3 初赛] 运气
      • 题目背景
      • 题目描述
      • 输入格式
      • 输出格式
      • 分析题意:
  • 2.P8837 [传智杯 #3 决赛] 商店
  • [传智杯 #3 决赛] 商店
    • 题目背景
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
      • 分析题意:
  • 3[传智杯 #2 决赛] 补刀
    • 题目描述
    • 输入格式
    • 输出格式
    • 样例 #1
      • 样例输入 #1
      • 样例输出 #1
    • 提示
      • 分析题意:
  • 总结

提示:以下是本篇文章正文内容,下面案例可供参考


前言

    给大家推荐一个刷题网站:洛谷,提高我们的算法能力的一个重要途径就是刷题,废话不多说,开始!

1.P8825 [传智杯 #3 初赛] 运气

题目背景

YYH Land(Yoauld,Youthful & Happy Land) 是位于炽蓝仙野的一片神奇的国度,那里的人们过着无拘无束的的快乐生活。

题目描述

哈兰·斯威提是 YYH Land 远近闻名的注铅骰子爱好者。有一天他碰到了这么一个问题:
你有一枚 6 个面的骰子,分别写了1, 2, 3, 4, 5, 6, 每一面朝上的概率是均等的。
现在哈兰想知道,如果他投掷 n 次,并且将结果按顺序写在纸上成为一个数。(比如说如果哈兰扔了
3 次,分别是3, 2, 5, 那么他最后得到的数就是325). 他现在想知道这个数是 k 的倍数的可能情况有多少种,其中 k 是一个特定的数。

输入格式

一行两个整数 n,k ,意义如题所示。

输出格式

一行一个整数,表示答案。
输入输出样例

输入 #1         输出

2 11        6

数据规模与约定
对于 40% 的数据,满足 n 分别为 1, 2, 3,4
对于 另外30% 的数据, 满足 1 <= k <= 3
对于 100% 的数据,满足 1<= n <= 10, 1<= k <=1000

分析题意:

在投掷n次骰子中,把每一次骰子掷出的点数组合在一起,求组合的数字对k取模==0的数有多少个,并且对结果对1e9 + 7取模,因为n 最多取到10,所以最大的数为6666666666,会爆int,所以最好要把数据类型定义为long long。并且我们可以根据数据范围 n <= 10来大致判断该题的算法,应该是dfs搜索或者是dp之类的,或者是一些入门题的模拟。

写法1:暴力模拟(过60%)
思路:找出n次掷出骰子的最小值和掷出骰子的最大值作为for循环的判断起始值和结束值。如果符合条件就ans++

#include
using namespace std;

const int mod = 1e9 + 7;
typedef long long ll;
int n, k;
string s;
ll ans = 0;
bool cheak(ll x)
{
    
    while(x)
    {
        int h = x % 10;
        x /= 10;
        if(h > 6 || h == 0) 
        {
            return false;
        }
    }
    return true;
}
int main ()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin >> n >> k;
    //直接考虑k的倍数,如果k的倍数出现>6 &&=0的直接pass,还有位数,后面直接输出答案
    ll Max = 6;
    ll Min = 1;
    while(n > 1)
    {
        Max *= 10;
        Max += 6;
        Min *= 10;
        Min += 1;
        n--;
    }
    int f = (Min - 1) / k;
     for(int i = f; (ll)i * k <= Max; i++)
     {
         if( cheak(i * k) && i * k >= Min) ans++;
     }
     ans %= mod;
    cout << ans << endl;
    return 0;
}

【传智杯】初赛部分题解_第1张图片
写法2:dfs深搜 写法很简单

#include
using namespace std;
typedef long long ll;

const int mod = 1e9 + 7;
ll n, k, ans;
void dfs(int u, ll sum) //记得这里的sum要ll,否则会卡
{
    if(u == n) //判断结束条件,次数到n
    {
        if(sum % k == 0) ans++;
        return;
    }
    for(int i = 1; i <= 6; i++) dfs(u + 1, sum + 10 * i);
    //非常简单的dfs
}

int main ()
{
    cin >> n >> k;
    dfs(0, 0); //第一个参数是次数,第二个参数是现在骰子总的结合点数
    
    cout << ans << endl;
    return 0;
}

在这里插入图片描述

2.P8837 [传智杯 #3 决赛] 商店

[传智杯 #3 决赛] 商店

题目背景

disangan333 想给 disangan233 买一个礼物,于是他和你一起逛商店。

题目描述

n n n 名同学去逛商店,店里有 m m m 个物品,第 i i i 人有 w i w_i wi 块钱,第 i i i 个物品价格 c i c_i ci 元。

每个人至多买一个物品,每个物品只能被买一次,问最多有多少人能买到物品。

对于所有数据, n , m ≤ 1 0 5 n,m \leq 10^5 n,m105 w i , c i ≤ 1 0 9 w_i,c_i\leq 10^9 wi,ci109

输入格式

输入共 3 3 3 行。

1 1 1 行输入 2 2 2 个正整数 n , m n,m n,m

2 2 2 行输入 n n n 个整数 w 1 … w n w_1\ldots w_n w1wn w i w_i wi 表示第 i i i 人的钱。

3 3 3 行输入 m m m 个整数 c 1 … c m c_1\ldots c_m c1cm c i c_i ci 表示第 i i i 个物品的价格。

输出格式

对于所有数据, n , m ≤ 1 0 5 n,m \leq 10^5 n,m105 w i , c i ≤ 1 0 9 w_i,c_i\leq 10^9 wi,ci109

样例 #1

样例输入 #1

15 20
4 3 9 10 7 7 5 3 6 1 8 6 6 1 5 
12 4 1 9 8 5 8 6 4 5 18 8 14 9 9 7 20 11 8 19

样例输出 #1

10

分析题意:

题目是要我们求最多有多少人能买到物品,而每个人的钱和物品价值都是没有顺序的,因此我们要把每个人的钱和物品价值都从小到大排序一遍,然后for循环人数, 如果这个人的钱数 > 物品价值,答案++,物品c++。

写法:C++

#include
using namespace std;

const int N = 1e5 + 10;
int a[N], v[N];
int n, m;

int main ()
{
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= m; i++) cin >> v[i];
    
    sort(a + 1, a + n + 1);
    sort(v+1, v+m+1);
    int ans = 0;
    int  c = 1;
    for(int i = 1; i <= n; i++)
    {
        if(a[i] >= v[c]) {
            ans++;
            //cout << a[i] << " " << v[c] << " ";
            c++;
        }
    }
    cout << ans << endl; 
    return 0;
}

3[传智杯 #2 决赛] 补刀

题目描述

UIM 在写程序的空闲玩一款 MOBA 游戏。

【传智杯】初赛部分题解_第2张图片

当敌方的小兵进入到我方防御塔的范围内,就会持续受到防御塔造成的伤害;当然我方英雄也可以对它造成伤害。当小兵的血量降到了 0 或者更低,就会被击杀。为了获得经验,UIM 希望在防御塔将这个小兵杀死之前,亲自补刀将其击杀。

为了简化问题,我们假设这个小兵有 h h h 点的生命值。每次防御塔的攻击可以给小兵造成 x x x 点伤害,而你的英雄每次攻击可以给小兵造成 y y y 点伤害。你的攻击速度和防御塔攻击速度相同,所以你可以在防御塔第一次攻击小兵之前,或者每次防御塔攻击之后,选择是否对小兵进行一次攻击,当然你也可以选择不攻击。

现在想知道,给出这些信息,判断英雄是否有办法将这个小兵击杀?

输入格式

每个测试点由多组数据组成。

输入第一行,包含一个正整数 T T T,表示数据组数。

接下来 T T T 行,每行三个非负整数 h , x , y h,x,y h,x,y,其意义已经在题目描述中给出。

输出格式

输出 T T T 行。对于每组数据,如果可以最后将小兵击杀,输出 Yes,否则输出 No

样例 #1

样例输入 #1

5
100 100 1
100 97 1
100 98 1
100 99 1
100 100 0

样例输出 #1

No
No
Yes
Yes
No

提示

数据的组数不多于 50, 1 ≤ h ≤ 1 0 18 1\le h \le 10^{18} 1h1018 0 ≤ x , y ≤ 1 0 18 0\le x,y \le 10^{18} 0x,y1018

分析题意:

题目要我们求的判断英雄是否有办法将这个小兵击杀。
具体有以下几种情况
1:如果我一次就能击杀小兵       y >= h       Yes
2:如果塔一次就能击杀小兵       x >= h       No
3:如果塔伤 == 0       Yes
4:如果英雄伤害 == 0       No
计算攻击的次数 ti = h/x + 1; 计算 小兵最后被塔攻击剩余的血量 h = h % x;
f(h == 0)h = x;//如果打没血了,就少打一次
最后判断英雄是否能击杀小兵

代码示例:

#include
using namespace std;
typedef long long ll;
int t;
ll h, x, y;
void solve()
{
    cin >> h >> x >> y;
    if(y >= h){
        cout << "Yes" << endl;
        return;
    }
    if(x >= h)
    {
        cout << "No" << endl;
        return;
    }
    if(y == 0)
    {
        cout << "No" << endl;
        return;
    }
    if(x == 0){
        cout << "Yes" << endl;
        return;
    }
    long long ti = h/x + 1;
    h = h % x;
    if(h == 0)h = x;//如果打没血了,就少打一次
    if((ti) * y >= h){
        cout << "Yes" << endl;
        return;
    }else{
        cout << "No" << endl;
        return;
    }
    
}
int main ()
{
    cin >> t;
    while(t --)
    {
        solve();
    }
    
    
    return 0;
}

总结

    这次和大家分享了传智杯的几题普及/普及+难度的题,希望大家读后能有所收获!

你可能感兴趣的:(蓝桥杯,c++,深度优先,贪心算法)