IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 牛客练习赛86(A~C题解) -> 正文阅读

[数据结构与算法]牛客练习赛86(A~C题解)

题解篇(牛客练习赛86)

牛客练习赛86,难度适中,前三题分别为博弈、构造、贪心DP,第三题较难,比赛中没有写出来, 但好在前两题手速比较快,所以这场比赛也没掉分;

A、 取因数

在这里插入图片描述
题意:A和B玩数字游戏,开始给出一个数字n,A先减去这个数字的一个因数x,将数字n变为n-x,而后B同样找出一个因数,让变换后的数字减去这个因数,以此类推,最后谁先把数字变成0,谁就输了。

题目要求A和B都用最优策略解决,很明显的博弈题目;

解题思路:将数字n分为两种情况, 奇数和偶数;
1、对于每一个数字n,若n为奇数,则它的因数只有奇数(因为偶乘偶得偶,偶乘奇得偶,只有奇乘奇得奇),则奇数变换后一定是偶数;
2、对于每一个数字n,若n为偶数,则它的因数一定有一个奇数1,则每一个偶数一定能变成奇数;

所以对于每一个数字n来回变化,每人都使用最优策略,则一定会有一次变为2,此时因数只有1,则2在谁手上,谁就能赢,化零为整,则n为偶数先手必胜,n为奇数后手必胜

#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
#include <unordered_map>
 
using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 100005;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;

int main()
{
    ios::sync_with_stdio(false), cout.tie(0), cin.tie(0);
    int n;
    cin>>n;
    if(n%2 == 0)cout<<"Alice"<<endl;
    else cout<<"Bob"<<endl;
    return 0;
}

B、A+B

在这里插入图片描述
题意:构造一个字符串s(仅包含数字),使得s能按顺序分解成三个字符串a、b、c(a+b+c = s),他们转换为数字的情况下满足数学计算a+b = c,一个字符串s有k种分割方式;给出n和k;构造出n个字符串,每个字符串有k种分割方式。

解题思路:k的取值范围是0~2,由此可以对不同的k分类讨论:
1、当k等于0时比较简单,可以构造出字符串x0yz,因为不能含有前导零,则只能分解成x0,y和z,此时无论x,y,z为何数,皆满足k为0;
2、当k等于1时,可以构造出形如xyzw0xyzw的模式此时只包含算式xyzw+0 = xyzw;
3、当k等于2时,可以构造出形如11111122 这类的111+11 = 122,11+111 = 122,这类的x+y = z,y+x = z;
此时可以令x不变y公差为一递增,达到上限时将x赋值为222再以相同的方式递增;

int main()
{
    // ios::sync_with_stdio(false), cout.tie(0), cin.tie(0);
    int n, k;
    cin>>k>>n;
    if(k == 0){
        int x = 1;
        int y = 23;
        int t = 1;
        while(n--){
            printf("%d0%d\n", x, y);
            y++;
            if(y>=100&&t){
                t = 0;
                x = 2;
                y = 34;
            }
        }
    }
    else if(k == 1){//这里和上面说的构造方法不一样,但是上面的k = 1的构造方法更加简单
        int x = 1, y = 2;
        int t = 1;
        while(n--){
            printf("%d%d%d\n", x, y, x+y);
            y++;
            if(y>9){
                y = 1;
                x++;
                if(x>10&&t){
                    x = 101;
                    t = 0;
                }
                else if(x>100&&!t){
                    x = 1001;
                }
            }
        }
    }
    else if(k == 2){
        int x = 111;
        int y = 11;
        int t = 1;
        while(n--){
            printf("%d%d%d\n", x, y, x+y);
            y++;
            if(y>=100&&t){
                t = 0;
                x = 222;
                y = 11;
            }
        }
    }
    return 0;
}

C、取钱

在这里插入图片描述

题意:题意不难理解,看题目就行;

解题思路:首先,数据范围较大,但凑取纸币需要找到当前纸币集合(a)内最大的比b小的数,由此先想到二分,那么对于每个b怎样才能使得所取的面额x得到的纸币数量最多;
首先预处理dp数组,dp[i]表示最多取面值为a[i]时最多能取多少张(i>=2,因为a1恒为1),设此时面额为x;则x不可能取a[i](取a[i]就直接为一张),则对a[i]-1操作 找到a[i]-1最多能凑成的多少张,将其减少一张a[i-1],将其替换为dp[i-1],然后比较一下哪个比较大;

#include <iostream>
#include <algorithm>
#include <map>
#include <cstring>
#include <queue>
#include <cmath>
#include <vector>
#include <unordered_map>

using namespace std;
typedef long long ll;
typedef long double ld;
const int N = 2e5+5;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;

ll a[N];
pair<ll, ll> dp[N];
ll n;

pair<ll, ll> lq(ll x){
    if(x == 0) return {0,0};
    ll res = upper_bound(a+1, a+n+1, x) - a;
    res--;//最大的小于x的数
    ll num = x%a[res];
    ll u = x/a[res];
    ll ans = u;
    ll cnt = u*a[res];
    pair<ll, ll> t = lq(num);
    if(dp[res].first +u-1 >= ans+t.first){
        ans = dp[res].first+u-1;
        cnt = dp[res].second+(u-1)*a[res];
    }
    else{
        ans = ans+t.first;
        cnt = cnt+t.second;
    }
    return {ans, cnt};
}

int main()
{
    // ios::sync_with_stdio(false), cout.tie(0), cin.tie(0);
    scanf("%lld", &n);
    for(int i = 1; i<=n; i++)scanf("%lld", &a[i]);
    dp[1].first = 0, dp[1].second = 0;
    for(int i = 2; i<=n;i++){
        ll x = a[i]-1;
        pair<ll, ll>t = lq(x);
        dp[i] .first = t.first;
        dp[i].second = t.second;
    }
    //  for(int i = 1; i<=n; i++) cout<<dp[i].first<<' '<<dp[i].second<<endl;
    int q;
    scanf("%d", &q);
    while(q--){
        ll x;
        scanf("%lld", &x);
        pair<ll, ll>t = lq(x);
        printf("%lld %lld\n", t.second, t.first);
    }
    return 0;
}

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-07-11 16:51:09  更:2021-07-11 16:52:50 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/9 5:51:28-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码