2024牛客寒假算法基础集训营1 补题
2024牛客寒假算法基础集训营1 补题
A.DFS搜索 模拟
题意:
给你一个字符串 “DFS“
和"dfs"
。
思路:
直接模拟即可
参考代码:
#include<bits/stdc++.h>
using namespace std;
#define ff first
#define ss second
#define eb emplace_back
#define all(u) u.begin(), u.end()
#define endl '\n'
#define debug(x) cout<<#x<<":"<<x<<endl;
typedef pair<int, int> PII;
typedef long long LL;
const int inf = 0x3f3f3f3f;
const int N = 1e5 + 10, M = 105;
const int mod = 1e9 + 7;
const int cases = 1;
void Showball(){
int n;
cin>>n;
int c1=0,c2=0;
while(n--){
char c;
cin>>c;
if(c1==0&&c=='D') c1++;
if(c1==1&&c=='F') c1++;
if(c1==2&&c=='S') c1++;
if(c2==0&&c=='d') c2++;
if(c2==1&&c=='f') c2++;
if(c2==2&&c=='s') c2++;
}
cout<<(c1==3)<<" "<<(c2==3)<<endl;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(nullptr);
cout.tie(nullptr);
int T=1;
if(cases) cin>>T;
while(T--)
Showball();
return 0;
}
B 关鸡 思维+模拟
题意:
有一个
现在给出一些有火格子的坐标,问你最少还需要添加几个有火的格子,可以保证鸡走不出地图。
思路:
很明显,想要堵住鸡通过的路,有三种情况:
那么如果左边和右边都有前三种情况中的任意一种即可。
当然还有一种特殊情况,即图中的情况4。
这种情况只需要三个有火的格子即可。
判断以上情况是否存在,以及需要补充的块数即可。
参考代码:
void Showball(){
int n;
cin>>n;
set<int> f,s;
while(n--){
int r,c;
cin>>r>>c;
if(r==1) f.insert(c);
else s.insert(c);
}
bool l=false,r=false;
bool ll=false,rr=false;
for(auto k:f){
if(k<0){
if(s.count(k-1)||s.count(k)||s.count(k+1)) ll=true;
else l=true;
}else if(k>0){
if(s.count(k-1)||s.count(k)||s.count(k+1)) rr=true;
else r=true;
}
}
for(auto k:s){
if(k<0){
l=true;
}else if(k>0){
r=true;
}
}
int ans1=3-s.count(0)-f.count(1)-f.count(-1);
int ans=4;
if(ll) ans-=2;
if(rr) ans-=2;
if(!ll&&(l||s.count(0))) ans--;
if(!rr&&(r||s.count(0))) ans--;
cout<<min(ans1,ans)<<endl;
}
C 按闹分配 前缀和
题意:
有
现在又来了一个人,办事需要
现在给出
思路:
首先,根据题意,我们可知求出初始不满意度
我们考虑在
那么由题意可知,
参考代码:
void Showball(){
int n,q,t;
cin>>n>>q>>t;
vector<int> a(n);
vector<LL> s(n+1);
for(int i=0;i<n;i++) cin>>a[i];
sort(all(a));
for(int i=0;i<n;i++) s[i+1]=s[i]+a[i];
while(q--){
LL m;
cin>>m;
LL id=max(0LL,n-m/t);
cout<<s[id]+t<<endl;
}
}
D 数组成鸡 数学 预处理
题意:
给你
你可以操作任意次。给
为
思路:
我们知道
那么我们就可以
存到
参考代码:
const int K = 4e4;
void Showball(){
int n,q;
cin>>n>>q;
vector<int> a(n);
map<int,int> mp;
for(int i=0;i<n;i++){
cin>>a[i];
mp[a[i]]++;
}
sort(all(a));
a.erase(unique(all(a)),a.end());
int N=a.size();
auto qmi=[&](int a,int b){//快速幂
int res=1;
while(b){
if(b&1){
if(1LL*res*a>=inf) return inf;
res*=a;
}
a=min(1LL*inf,1LL*a*a);
b>>=1;
}
return res;
};
set<int> s;
s.insert(0);
if(N<=20){
for(int i=0;i<N;i++){
for(int k=-a[i]-K;k<=-a[i]+K;k++){//-K<=a[i]+k<=K
int res=1;
for(int j=0;j<N;j++){
int x=a[j]+k,y=mp[a[j]];
int v=qmi(x,y);
if(abs(1LL*res*v)>=inf){
res=inf;
break;
}
res*=v;
}
if(abs(res)<inf) s.insert(res);
}
}
}
while(q--){
int x;
cin>>x;
cout<<(s.count(x)?"Yes\n":"No\n");
}
}
E 本题又主要考察了贪心 搜索
题意:
有
获胜加
现在让你求出
思路:
看数据范围很小,果断搜索。我们注意到对局只有三种情况,那么直接枚举三种对局情况即可。
代码参考jiangly
,自己赛时写的太臃肿了。
参考代码:
void Showball(){
int n,m;
cin>>n>>m;
vector<int> a(n),u(m),v(m);
for(int i=0;i<n;i++) cin>>a[i];
for(int i=0;i<m;i++){
cin>>u[i]>>v[i];
u[i]--,v[i]--;
}
int ans=n;
auto dfs=[&](auto self,int i)->void{
if(i==m){
int res=1;
for(int j=0;j<n;j++) res+=(a[j]>a[0]);//O(n)判断排名,不像我傻傻二分
ans=min(ans,res);
return;
}
for(auto [x,y]:{make_pair(3,0),{0,3},{1,1}}){//这一步枚举太简洁了
a[u[i]]+=x;
a[v[i]]+=y;
self(self,i+1);
a[u[i]]-=x;
a[v[i]]-=y;
}
};
dfs(dfs,0);
cout<<ans<<endl;
}
F 鸡数题! 第二类斯特林数
题意:
求出长度为
1.数组值全为正数
2.数组值严格单调增
3.数组值按位或之和为
4.任意两个数组值按位与结果为
思路:
根据题意,转化一下就是数组中的
那么问题转化为问题转变为
参考代码:
//预处理组合数
int fact[N],infact[N];
int qmi(int a,int k,int p){
int res=1%p;
while(k){
if(k&1) res=(LL)res*a%p;
a=(LL)a*a%p;
k>>=1;
}
return res;
}
void init(int n){
fact[0]=infact[0]=1;
for(int i=1;i<=n;i++){
fact[i]=(LL)fact[i-1]*i%mod;
infact[i]=(LL)infact[i-1]*qmi(i,mod-2,mod)%mod;
}
}
int C(int a,int b){
return (LL)fact[a]*infact[b]%mod*infact[a-b]%mod;
}
//第二类斯特林数
int Stirling2(int n,int m){
init(m);
LL res=0;
for(int k=0;k<=m;k++){
if(k&1){
res=(res-1LL*C(m,k)*qmi(m-k,n,mod)%mod+mod)%mod;
}else{
res=(res+1LL*C(m,k)*qmi(m-k,n,mod)%mod)%mod;
}
}
return res*infact[m]%mod;
}
void Showball(){
int n,m;
cin>>n>>m;
cout<<Stirling2(n,m)<<endl;
}
G why送外卖 贪心 前缀和
题意:
现在有
思路:
因为满减卷可以叠加使用,所以我们可以按照原价从小到大排序,因为可以叠加使用,所以可以求一下前缀和,满足条件就更新答案。
参考代码:
void Showball(){
int n,m;
cin>>n>>m;
vector<PII> a(n);
for(int i=0;i<n;i++) cin>>a[i].ff>>a[i].ss;
sort(all(a));
vector<LL> s(n+1);
for(int i=0;i<n;i++) s[i+1]=s[i]+a[i].ss;
LL ans=m;
for(int i=0;i<n;i++){
if(a[i].ff-s[i+1]<=m) ans=m+s[i+1];
}
cout<<ans<<endl;
}
H 01背包,但是bit 位运算 lowbit
题意:
求出总重量不超过
思路:
我们注意到按位或不能超过
也可以是
所以满足这个性质的我们就可以进行选择。接着我们枚举
需要优化,设我们当前枚举的数是
举个例子:
我们发现蓝色的就是跳过
考代码:
void Showball(){
int n,m;
cin>>n>>m;
vector<int> v(n),w(n);
for(int i=0;i<n;i++) cin>>v[i]>>w[i];
auto calc=[&](int x){//计算体重按位或小于等于x的价值之和
LL res=0;
for(int i=0;i<n;i++){
if((x&w[i])==w[i]) res+=v[i];
}
return res;
};
LL ans=calc(m);
for(int i=m;i;i-=(i&-i)){//lowbit(i)=i&-i;
ans=max(ans,calc(i-1));
}
cout<<ans<<endl;
}
I It's bertrand paradox. Again! 思维
题意:
给出了两种生成
第一种方式:等概率在
一直重新随机生成半径,直到满足要求为止。
第二种方式:等概率在
一直重新随机生成圆心坐标和半径,直到满足要求为止。
思路:
注意到,第一种生成的圆的圆心会更加分散,并且每个区域会比较平均。第二种生成的圆的圆心会更加靠近中间。
那么我们只要取一个中间区域的圆心数量,就可以判断是第一种还是第二种。
对于圆心
参考代码:
void Showball(){
int n;
cin>>n;
int cnt=0;
for(int i=0;i<n;i++){
int x,y,r;
cin>>x>>y>>r;
if(-9<=x&&x<=9&&-9<=y&&y<=9) cnt++;
}
if(cnt<=n*0.01) cout<<"bit-noob\n";
else cout<<"buaa-noob\n";
}
J 又鸟之亦心 二分答案
题意:
有一对情侣他们的初始位置分别是
求出情侣两人相隔距离的最大值最小是多少?
思路:
最大值最小,经典的二分答案模型。
难点在于check()函数如何去写。
我们可以把能够完成的任务放到
不存在直接return false
。对于如何判断是否存在满足条件的情况。我们可以把不满足情况
的都删去,然后判断
参考代码:
void Showball(){
int n;
cin>>n;
vector<int> a(n+2);
for(int i=0;i<n+2;i++) cin>>a[i];
auto check=[&](int d){
set<int> s;
s.insert(a[0]);
for(int i=1;i<n+2;i++){
if(s.empty()) return false;
if(*s.rbegin()>a[i]+d) s.erase(s.upper_bound(a[i]+d),s.end());
if(!s.empty()&&*s.begin()<a[i]-d) s.erase(s.begin(),s.lower_bound(a[i]-d));
if(abs(a[i]-a[i-1])<=d) s.insert(a[i-1]);
}
return !s.empty();
};
int l=abs(a[0]-a[1]),r=1e9;
while(l<r){
int mid=l+r>>1;
if(check(mid)) r=mid;
else l=mid+1;
}
cout<<l<<endl;
}
K 牛镇公务员考试 置换环
题意:
给你
则第
A:
B:
C:
D:
E:
求出能够全部题目回答正确的答案有多少种?
思路:
看到这种
找到环,然后删除环外的链。接着枚举所有可能选项,如果通过环一圈得到的选项和原来一致。
那么就是可行解。乘法原理统计即可。
参考代码:
void Showball(){
int n;
cin>>n;
vector<int> a(n);
vector<string> s(n);
for(int i=0;i<n;i++){
cin>>a[i]>>s[i];
a[i]--;
}
vector<int> st(n);
LL ans=1;
for(int i=0;i<n;i++){
int t=i;
vector<int> c;
while(!st[t]){
st[t]=true;
c.eb(t);
t=a[t];
}
auto it=find(all(c),t);
if(it!=c.end()){
c.erase(c.begin(),it);//删除环之外的部分
int res=0;
for(char ch='A';ch<='E';ch++){
char cur=ch;
for(auto x:c){
cur=s[x][cur-'A'];
}
res+=(cur==ch);
}
ans=ans*res%mod;
}
}
cout<<ans<<endl;
}
L 要有光 思维
题意:
一束光打在距离光源为
思路:
显然,这个面积是一个定值。根据相似三角形,最后阴影面积就是一个上底为
参考代码:
void Showball(){
int c,d,h,w;
cin>>c>>d>>h>>w;
cout<<3*w*c<<endl;
}
M 牛客老粉才知道的秘密 签到
题意:
题目一次最多只能展示六道题目,多余的题目需要进行左滑或右滑展示。
现在给你题目总数,问你出现在最左边的题目有几种情况。
思路:
很明显,答案是题数
参考代码:
void Showball(){
int n;
cin>>n;
int ans=n/6;
if(n%6!=0) ans*=2;
cout<<ans<<endl;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!