笔试练习day15


感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 C语言
🐿️🐿️🐿️ C语言例题
🐣🐣🐣 python
🐓🐓🐓 数据结构C语言
🐔🐔🐔 C++
🐿️🐿️🐿️ 文章链接目录
🏀🏀🏀 笔试练习题
😎😎😎 实习日记
🐯🐯🐯 Git

平方数

平方数链接
在这里插入图片描述

题目解析

这道题就是求给出一个数,理他最近的平方数,这道题我们可以直接用sqrt函数,他是在math.h文件里面的,当我们用的时候,他会将结果向下取整
另外我们还需要注意一点,这道题的数据范围有点大,我们要用long long类型,不然存不下

代码

# include<iostream>
# include<math.h>
using namespace std;
int main()
{
    long long x;
    cin>>x;
    long long count=sqrt(x);
    if(x-count*count<(count+1)*(count+1)-x)
        cout<<count*count;
    else
        cout<<(count+1)*(count+1);
    return 0;
}

分组(需要重做)

分组链接在这里插入图片描述

在这里插入图片描述

题目解析

这道题要注意有几种声部,如果声部类型大于分组的数量,那么就肯定是不可能分成功的,如果是小于的话就需要我们合理的进行分配了在这里插入图片描述

首先我们可以先统计每个声部有多少人
对于分小组,如果我们直接拿着人数分,这样是不行的,因为我们不确定一个类型的声部应该要分多少组,以及多少人

方法一 :
但是如果我们假设每个组最多分x人,然后一个一个的枚举,那么我们就可以确定需要分多少组了
在这里插入图片描述

比如第一组有8个人,我们以每3人为一组,这样我们很容易就能得出需要分多少组,具体公式就是下面这个
最后我们需要判断当最多人数为x时,分的组是否小于等于m组,因为如果小于的话,我们可以将一些组里面的人数进行拆分,然后再进行分组
另外x的最大值和最小值确定方法如下
x的最小值就是一人一组,最大值就是人数最多的那个声部
我们就从1开始一直枚举,当出现所以组数相加小于等于m组时,就是最终结果

方法二:
这个方法是对上面解法的一种优化
在这里插入图片描述

因为上面的做法是从小到大一直找
但是如果我们从中间开始用二分查找的方法取找的话就可以降低时间复杂度

代码

方法一暴力枚举
#include<iostream>
using namespace std;
int arr[100000]={0};
  int n,m;
bool check(int x)
{
    int g=0;
    for(int i=1;i<=n;i++)
        g+=arr[i]/x+(arr[i]%x==0?0:1);
    return g<=m;
}
int main()
{
  int hmax,x;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        hmax=max(hmax,++arr[x]);
    }
    int kinds=0;
    for(int i=1;i<=100000;i++)if(arr[i]!=0)kinds++;
    if(kinds>m)cout<<-1<<endl;
    else
    {
        for(int i=1;i<=hmax;i++)
        {
            if(check(i))
            {
                cout<<i<<endl;
                break;
            }
}
    }
    return 0;
}

这个解法可以换一种形式去写

#include<iostream>
#include<unordered_map>
using namespace std;
unordered_map<int,int>arr;
  int n,m;
bool check(int x)
{
    int g=0;
    for(auto&[a,b]:arr) g+=b/x+(b%x==0?0:1);
    return g<=m;
}
int main()
{
  int hmax,x;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        hmax=max(hmax,++arr[x]);
    }
    int kinds=arr.size();
    if(kinds>m)cout<<-1<<endl;
    else
    {
        for(int i=1;i<=hmax;i++)
        {
            if(check(i))
            {
                cout<<i<<endl;
                break;
            }
}
    }
    return 0;
}
代码解析

unordered_map<int,int>arr是一个arr的哈希表,也就是上面的数组arr

bool check(int x)这个封装的函数是用来判断以x人为一组所分的组是否小于规定要求的m组,如果大于的话就说明不管怎么分都无法满足题目要求的m组

auto&[a,b]:arr 这里的a存的是声部的类型,b表示的是声部的人数

int kinds=arr.size()求的是有多少种不同的声部

方法二二分
#include<iostream>
#include<unordered_map>
using namespace std;
unordered_map<int,int>arr;
  int n,m;
bool check(int x)
{
    int g=0;
    for(auto&[a,b]:arr) g+=b/x+(b%x==0?0:1);
    return g<=m;
}
int main()
{
  int hmax,x;
    cin>>n>>m;
    for(int i=0;i<n;i++)
    {
        cin>>x;
        hmax=max(hmax,++arr[x]);
    }
    int kinds=arr.size();
    if(kinds>m)cout<<-1<<endl;
    else
    {
       int l=1,r=hmax;
        while(l<r)
        {
            int mid=(l+r)/2;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        cout<<l<<endl;
    }
    return 0;
}

AB13 【模板】拓扑排序(需要重做)

AB13 【模板】拓扑排序链接
在这里插入图片描述

题目解析

这里的拓扑排序是一个很陌生的名字
比如一堆事情,有先后顺序,你要排个顺序出来。

比如:
做菜流程
课程学习顺序
零件组装顺序
软件编译顺序
项目任务安排

这些事情不是随便做的,而是某些事必须在另外一些事情完成之后才能做

在这里插入图片描述
这个顺序就是1 → 2 → 3
拓扑排序只适用于:
有向无环图
有向:有方向的关系(谁依赖谁)
无环:不能有死循环(比如A依赖B,B依赖A)

我们以题目实例为例子
在这里插入图片描述
这里的5表示的是5个点,4表示的是4条边
后面输入的都是点与点之间的关系,画出的图如下
1和2有关系,我们用线链接起来 2和3也有关系…总之有关系的我们都链接起来
在这里插入图片描述

代码

#include <iostream>
#include<vector>
#include<queue>
using namespace std;
const int N = 2e5 + 10;
vector<vector<int>> edges(N);
int in[N];
int n, m;
queue<int> q;
vector<int> ret;
int main() {
    cin >> n >> m;

    while (m--) {
        int a, b;
        cin >> a >> b;
        edges[a].push_back(b);
        in[b]++;
    }
    for (int i = 1; i <= n; i++)if (in[i] == 0)q.push(i);
    while (q.size()) {
        int a = q.front();
        q.pop();
        ret.push_back(a);
        for (auto b : edges[a]) {
            if (--in[b] == 0)q.push(b);
        }
    }
    if (ret.size() == n) {
        for (int i = 0; i < n - 1; i++)cout << ret[i] << " ";
        cout << ret[n - 1];
    } else cout << -1 << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值