2024牛客寒假算法基础集训营1(补题)

2024-02-28 20:28

本文主要是介绍2024牛客寒假算法基础集训营1(补题),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

  • A
  • B
  • C
  • D
  • E
  • F
  • G
  • H
  • I
  • J
  • K
  • L

A

n的范围很小暴力直接 O ( n 3 ) O(n^3) O(n3)直接做就行。
我还傻的统计了一下前后缀,不过怎么写都行这道题。

#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define ls p<<1
#define rs p<<1|1
#define PII pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define debug(a) cout<<#a<<"="<<a<<endl;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f 
#define x first
#define y secondusing namespace std;const int N=30,mod=1e9+7;
int n,m,a[N],b[N],k;
int f[60][60];
char s[60];
int l[60],r[60]; 
bool st=false;void solve()
{int n;cin>>n;rep(i,1,59)	l[i]=r[i]=0;cin>>(s+1);//DFSmap<char,int>cnt;rep(i,1,n){if(cnt.find('D')!=cnt.end())	l[i]=1;cnt[s[i]]=1;}cnt.clear();fep(i,n,1){if(cnt.find('S')!=cnt.end())	r[i]=1;cnt[s[i]]=1;}//bool st=1;rep(i,1,n){if(s[i]=='F'&&l[i]==1&&r[i]==1){cout<<1<<' ';st=0;break;}}if(st)	cout<<0<<' ';//dfsst=1;rep(i,1,59)	l[i]=r[i]=0;cnt.clear();rep(i,1,n){if(cnt.find('d')!=cnt.end())	l[i]=1;cnt[s[i]]=1;}cnt.clear();fep(i,n,1){if(cnt.find('s')!=cnt.end())	r[i]=1;cnt[s[i]]=1;}rep(i,1,n){if(s[i]=='f'&&l[i]==1&&r[i]==1){cout<<1<<' ';st=0;break;}}if(st)	cout<<0<<' ';cout<<endl;
}signed main()
{IOS	
//  	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

B

赛时的思路是:周围三个点特判,然后左边求最小和右边求最小,最后和特判取最小。
代码写的比较一坨很乱,最后也没调出来。
遇见这种感觉还是重写吧。
主要就是分类讨论

  1. 看鸡左边被堵没有
  2. 看鸡右边被堵没有
  3. 看鸡左边有没有火
  4. 看鸡右边有没有火
  5. 特判(2,0)
    自己写的太丑了,放一份加了注释的jls的代码吧。
#include <bits/stdc++.h>using i64 = long long;void solve() {int n;std::cin >> n;//left1表示左边是否有火,right1表示右边是否有火//left2表示左边是否能堵住鸡,right2表示右边是否能堵住鸡int left1 = 0, left2 = 0;int right1 = 0, right2 = 0;std::set<std::pair<int, int>> s;for (int i = 0; i < n; i++) {int r, c;std::cin >> r >> c;if (c <= 0) {left1 = 1;}if (c >= 0) {right1 = 1;}s.emplace(r, c);}for (auto [r, c] : s) {if (!c) {continue;}//这里和3异或真的简化了很多代码if (s.count({r ^ 3, c}) || s.count({r ^ 3, c + (c > 0 ? -1 : 1)})) {if (c > 0) {right2 = 1;} else {left2 = 1;}}}int ans = 4 - left1 - left2 - right1 - right2;ans = std::min(ans, int(3 - s.count({2, 0}) - s.count({1, -1}) - s.count({1, 1})));std::cout << ans << "\n";
}int main() {std::ios::sync_with_stdio(false);std::cin.tie(nullptr);int t;std::cin >> t;while (t--) {solve();}return 0;
}

C


S m i n = 所有人办事的时间 + 等待时间 S_{min}=所有人办事的时间+等待时间 Smin=所有人办事的时间+等待时间
等待时间 = T 1 ∗ n + T 2 ∗ ( n − 1 ) + . . . + T n ∗ 1 等待时间=T_1 * n + T_2 * (n-1)+...+ T_n * 1 等待时间=T1n+T2(n1)+...+Tn1
这就转化成了一个经典的问题排序不等式
T 1 、 T 2 、 . . . 、 T n T_1、T_2、...、T_n T1T2...Tn按从小到大的对应和n~1相乘
然后看鸡能查到谁的前面


#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define ls p<<1
#define rs p<<1|1
#define PII pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define debug(a) cout<<#a<<"="<<a<<endl;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f 
#define x first
#define y secondusing namespace std;const int N=1e5+10,mod=1e9+7;
int n,q,tc;
int t[N],d[N];//x为鸡插队的时间
bool check(int x,int m)
{//找到受鸡插队影响的第一个位置 int l=1,r=n;int k=upper_bound(d+1,d+1+n,x)-d;int sum=(n-k+1)*tc;return sum<=m;
}void solve()
{cin>>n>>q>>tc;rep(i,1,n)	cin>>t[i];sort(t+1,t+1+n);int sm=0;//计算每个人不满意度,sm就是没插队的最小不满意度 //di也是每个人完成工作的时间 rep(i,1,n)	d[i]=d[i-1]+t[i],sm+=d[i];rep(i,1,q){int m;cin>>m;int l=0,r=d[n];while(l<r){int mid=(l+r)>>1;if(check(mid,m))	r=mid;else	l=mid+1;}cout<<l+tc<<endl;}
}signed main()
{IOS	
//   	freopen("1.in", "r", stdin);int _;
//	cin>>_;
//	while(_--)solve();return 0;
}

D

代码是参考jls的,写的真的很优雅
思路:
这里有一个小 t r i c k trick trick,数相乘的话会很大,而 M M M只有 1 e 9 1e9 1e9, 2 3 0 2^30 230就会到达 1 e 9 1e9 1e9
也就是说,不为0的数相乘很快会超范围有很多不合法的。
对于相同的数,平移的话是都是一样的。
我们考虑不同的数有多少个。
不同的数最多有20个,20个的话就会相乘就会超范围。
然后里面就暴力去瞎搞就行

#include <bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define _for(i,a,b) for(int i=(a); i<(b); ++i)
#define pii pair<int, int>
#define pdd pair<double,double>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define vi vector<int>using namespace std;
const int maxn=1e5+10,mod=1e9+7,K=4e4,inf=1e9;void solve() {int n,Q;cin>>n>>Q;map<int,int>cnt;rep(i,1,n) {int a;cin>>a;cnt[a]+=1;}set<int>s{0};//只有当不同的数为20个以内时乘起来才不会超出范围if(cnt.size()<=20) {//将map中的内容复制到vector中vector<pii>a(cnt.begin(),cnt.end());int n=a.size();int d=a[0].x-K;//枚举每一个数_for(i,0,n) {//枚举每一个数进行两种操作的总的变化量for(d=max(d,a[i].x-K); d<=a[i].first+K;d++) {//从前往后算一遍答案				int res=1;_for(j,0,n) {//看一下这个数会变成的数,vint v=a[j].x-d;//1的话对res没有影响if(v==1) {continue;}//-1的话看值为这个数的有多少个if(v==-1) {if(a[j].y%2==1) {res*=-1;}continue;}//两个都不是的话就把,所有值为这个数的都乘上去_for(c,0,a[j].y) {res*=v;//中间溢出范围直接退出if(abs(res)>inf) {break;}}//溢出的话直接退出if(abs(res)>inf) {break;}}//满足的话用set存一下,供查询if(abs(res)<=inf) {s.insert(res);}}}}while(Q--) {int M;cin>>M;if(s.count(M)) {cout<<"Yes"<<endl;} else {cout<<"No"<<endl;}}
}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("1.in", "r", stdin);int _;
//	cin>>_;
//	while(_--)solve();return 0;
}

E

e题看到数据范围n和m都很小,dfs,对于每场比赛,ab两位选手,考虑每场比赛。
ab两位选手

  1. a胜b败
  2. a败b胜
  3. ab平局
#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define ls p<<1
#define rs p<<1|1
#define PII pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define debug(a) cout<<#a<<"="<<a<<endl;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f 
#define x first
#define y secondusing namespace std;const int N=20,mod=1e9+7;
int n,m,ans;
struct node
{int val,idx;bool operator <(const node t){return val>t.val;}
}a[N],b[N];PII op[N];void dfs(int u)
{if(u==m+1){memcpy(b,a,sizeof a);sort(b+1,b+1+n);
//		cout<<"AAAAAA"<<endl;
//		rep(i,1,n)	cout<<a[i].idx<<' '<<a[i].val<<endl;int k=0;rep(i,1,n)	if(b[i].idx==1)	k=i;ans=min(ans,k);return;}int x=find(op[u].x),y=find(op[u].y);//x胜a[x].val+=3;dfs(u+1); a[x].val-=3;//y胜a[y].val+=3;dfs(u+1); a[y].val-=3;//平局a[x].val+=1;a[y].val+=1;dfs(u+1); a[x].val-=1;a[y].val-=1;
}void solve()
{cin>>n>>m;ans=n;rep(i,1,n){int x;cin>>x;a[i]={x,i};}int k=0;rep(i,1,m){int x,y;cin>>x>>y;if(x>y)	swap(x,y);op[++k]={x,y};}dfs(1);cout<<ans<<endl;return;
}signed main()
{IOS	
//  	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

F

考的是知识点 第二类斯特林数
从题目还是比较容易看出来这是一道第二类斯特林数的题目的,直接从前往后求一遍通项公式。
需要补一下组合数学的知识
d7039fd6bc9ff6fe6361180a79f2f5b.jpg
image

#include <bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define pdd pair<double,double>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define vi vector<int>using namespace std;
const int maxn=1e6+10,mod=1e9+7;int ksm(int a,int b, int p){int res=1;while(b){if(b&1)	res=res*a%p;a=a*a%p;b>>=1;	}return res;
}
int fac[maxn],invfac[maxn];
void solve() {int n,m;cin>>n>>m;
// 	vi fac(n+1),invfac(n+1);fac[0]=invfac[0]=1;rep(i,1,maxn){fac[i]=fac[i-1]*i%mod;invfac[i]=ksm(fac[i],mod-2,mod);}      int ans=0;rep(i,0,m){ans+=((m-i)&1?-1:1)*ksm(i,n,mod)%mod*invfac[i]%mod*invfac[m-i]%mod;ans%=mod;}cout<<(ans+mod)%mod<<endl;
}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("1.in", "r", stdin);int _;
//	cin>>_;
//	while(_--)solve();return 0;
}

G

前缀和,先对优惠卷按价格排序,然后根据优惠卷可叠加,我们可以知道只要优惠的钱+m>=商品原价就可以更新答案。

#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define ls p<<1
#define rs p<<1|1
#define PII pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define debug(a) cout<<#a<<"="<<a<<endl;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f 
#define x first
#define y secondusing namespace std;const int N=1e5+10,mod=1e9+7;
int n,m;
struct node
{int x,y;bool operator <(const node t){return x<t.x;	} 
}a[N];void solve()
{cin>>n>>m;rep(i,1,n)	cin>>a[i].x>>a[i].y;sort(a+1,a+1+n);int ans=0,sum=0;rep(i,1,n){sum+=a[i].y;if(sum+m>=a[i].x){ans=max(ans,sum+m);}}if(!ans)	cout<<m<<endl;else	cout<<ans<<endl;
}signed main()
{IOS	
//  	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

H

位运算贪心
涉及到位运算的题一定要把数字当成二进制串看
并且不存在进位意味着–位和位之间是独立的
一般都是贪心的考虑每一位。

对于m我们设第x位为1,设选中的物品与起来为sum,如果sum的第x位为0,那么第x位之后所有的位都是任意的

  • 枚举第x位
  • 选择物品的第x位是0
  • 选择物品的高位应该是m高位的子集
  • 低位任意

#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_backusing namespace std;void solve()
{int n,m;cin>>n>>m;vector<int>v(n+1),w(n+1);rep(i,1,n)	cin>>v[i]>>w[i];int ans=0;auto check=[&](int s){int res=0;rep(i,1,n){//==的优先级高于&if((s&w[i])==w[i]){res+=v[i];}}ans=max(ans,res);};check(m);fep(i,29,0){if((m>>i)&1){check(m^(1<<i)|((1<<i)-1));	}}cout<<ans<<endl;return;
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//   	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

I


两种方式的区别在于半径。
我们可以模拟题目中的过程然后在本地多跑几组数据看看r的均值有什么规律
技巧就是打表找规律


#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_backusing namespace std;
const int N=2010;int mod=1e9+7;void solve()
{int n;cin>>n;int s=0;rep(i,1,n){int x,y,r;cin>>x>>y>>r;s+=r;}if(s/n<20.0)	cout<<"bit-noob"<<endl;else	cout<<"buaa-noob"<<endl;return;
}
signed main()
{ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
//   	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

J

#include <bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define _for(i,a,b) for(int i=(a); i<(b); ++i)
#define pii pair<int, int>
#define pdd pair<double,double>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back
#define vi vector<int>using namespace std;
const int maxn=1e5+10,mod=1e9+7,K=4e4,inf=1e9;
int a[maxn];
int n,x,y;bool check(int tar) {set<int>S;if(abs(x-y)<=tar)	S.insert(y);int lst=x;rep(i,1,n){if(S.size()&&abs(a[i]-lst)<=tar){S.insert(lst);}while(S.size()&&abs(*S.begin()-a[i])>tar)	S.erase(*S.begin());while(S.size()&&abs(*S.rbegin()-a[i])>tar)	S.erase(*S.rbegin());lst=a[i];}return S.size();
}void solve() {cin>>n>>x>>y;rep(i,1,n) {cin>>a[i];}int l=0,r=1e9;while(l<r) {int mid=(l+r)>>1;if(check(mid)) {r=mid;} else {l=mid+1;}}cout<<l<<endl;
}signed main() {ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
//	freopen("1.in", "r", stdin);int _;
//	cin>>_;
//	while(_--)solve();return 0;
}

K

基环树

L


这道题应该是个签到题。主要是题面有点吓人。
直接考虑光源在最下面,这种情况地上的未被照射到的面积应该是最大的。
面积很好求,就是一个等腰梯形的面积。


#include <bits/stdc++.h> 
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define ls p<<1
#define rs p<<1|1
#define PII pair<int, int>
#define pll pair<long long, long long>
#define ll long long
#define ull unsigned long long
#define db double
#define endl '\n'
#define debug(a) cout<<#a<<"="<<a<<endl;
#define IOS ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#define INF 0x3f3f3f3f 
#define x first
#define y secondusing namespace std;const int N=1e5+10,mod=1e9+7;
int n,q,tc;void solve()
{int c,d,h,w;cin>>c>>d>>h>>w;db ans=1.0*(6*w)*c/2;printf("%.5lf\n",ans);
}
signed main()
{
// 	IOS	
//  	freopen("1.in", "r", stdin);int _;cin>>_;while(_--)solve();return 0;
}

这篇关于2024牛客寒假算法基础集训营1(补题)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/756533

相关文章

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

Python中的随机森林算法与实战

《Python中的随机森林算法与实战》本文详细介绍了随机森林算法,包括其原理、实现步骤、分类和回归案例,并讨论了其优点和缺点,通过面向对象编程实现了一个简单的随机森林模型,并应用于鸢尾花分类和波士顿房... 目录1、随机森林算法概述2、随机森林的原理3、实现步骤4、分类案例:使用随机森林预测鸢尾花品种4.1

MySQL中my.ini文件的基础配置和优化配置方式

《MySQL中my.ini文件的基础配置和优化配置方式》文章讨论了数据库异步同步的优化思路,包括三个主要方面:幂等性、时序和延迟,作者还分享了MySQL配置文件的优化经验,并鼓励读者提供支持... 目录mysql my.ini文件的配置和优化配置优化思路MySQL配置文件优化总结MySQL my.ini文件

Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)

《Python基于火山引擎豆包大模型搭建QQ机器人详细教程(2024年最新)》:本文主要介绍Python基于火山引擎豆包大模型搭建QQ机器人详细的相关资料,包括开通模型、配置APIKEY鉴权和SD... 目录豆包大模型概述开通模型付费安装 SDK 环境配置 API KEY 鉴权Ark 模型接口Prompt

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

康拓展开(hash算法中会用到)

康拓展开是一个全排列到一个自然数的双射(也就是某个全排列与某个自然数一一对应) 公式: X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且0<=a[i]<i,1<=i<=n。(a[i]在不同应用中的含义不同); 典型应用: 计算当前排列在所有由小到大全排列中的顺序,也就是说求当前排列是第

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

综合安防管理平台LntonAIServer视频监控汇聚抖动检测算法优势

LntonAIServer视频质量诊断功能中的抖动检测是一个专门针对视频稳定性进行分析的功能。抖动通常是指视频帧之间的不必要运动,这种运动可能是由于摄像机的移动、传输中的错误或编解码问题导致的。抖动检测对于确保视频内容的平滑性和观看体验至关重要。 优势 1. 提高图像质量 - 清晰度提升:减少抖动,提高图像的清晰度和细节表现力,使得监控画面更加真实可信。 - 细节增强:在低光条件下,抖

2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题

题库来源:安全生产模拟考试一点通公众号小程序 2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题是由安全生产模拟考试一点通提供,流动式起重机司机证模拟考试题库是根据流动式起重机司机最新版教材,流动式起重机司机大纲整理而成(含2024年流动式起重机司机证模拟考试题库及流动式起重机司机理论考试试题参考答案和部分工种参考解析),掌握本资料和学校方法,考试容易。流动式起重机司机考试技

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig