感谢各位大佬对我的支持,如果我的文章对你有用,欢迎点击以下链接
🐒🐒🐒 个人主页
🥸🥸🥸 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 【模板】拓扑排序(需要重做)
题目解析
这里的拓扑排序是一个很陌生的名字
比如一堆事情,有先后顺序,你要排个顺序出来。
比如:
做菜流程
课程学习顺序
零件组装顺序
软件编译顺序
项目任务安排
这些事情不是随便做的,而是某些事必须在另外一些事情完成之后才能做
这个顺序就是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;
}