2025牛客寒假算法基础集训营2 个人题解
A.一起奏响历史之音!
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){bool flag=false;for(int i=1;i<=7;i++){int x;cin>>x;if(x!=1 && x!=2 && x!=3 && x!=5 && x!=6){flag=true;}}if(flag) cout<<"NO"<<endl;else cout<<"YES"<<endl;}
int main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T=1;while(T--) solve();return 0;
}
B.能去你家蹭口饭吃吗
解题思路
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=5e5+10;
int a[N];
void solve(){int n;cin>>n;for(int i=1;i<=n;i++) cin>>a[i];sort(a+1,a+n+1);int ans=n/2+1;cout<<a[ans]-1<<endl;
}
signed main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T=1;while(T--) solve();return 0;
}
F.一起找神秘的数!
解题思路
- 题目要求x+y = x&y + x|y + x^y,容易发现当某一二进制位相同,即同时为0或者同时为1时满足要求,则答案为区间长度
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
void solve(){int l,r;cin>>l>>r;int ans=r-l+1;cout<<ans<<endl;}
signed main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;while(T--) solve();return 0;
}
G. 一起铸最好的剑!
解题思路
- 一开始卡了很久,以为是精度问题,写了python都没过
- 观察题目范围,n最大为1e9,容易知道答案次数不会很大,直接枚举即可
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define double long double
using namespace std;
void solve(){int n,m;cin>>n>>m;if(m==1){cout<<1<<endl;return;}int k=0;for(int i=1;i<=100;i++){int t=powl(m,i);if(t>=n){k=i;break;}}if(k==1){cout<<1<<endl;return;}
// cout<<" "<<k<<endl;int t1=powl(m,k-1);int t2=powl(m,k);int ans=0;if(llabs(t1-n)<=llabs(t2-n)){ans=k-1;}else ans=k;cout<<ans<<endl;
}
signed main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;while(T--) solve();return 0;
}
J. 数据时间?
解题思路
- 大模拟,可以通过substr函数得到时间,判断时间可以通过都转化为秒数进行比较,这样便于写代码
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
int t1st,t1ed,_t1st,_t1ed;
int t2st,t2ed;
int t3st,t3ed,_t3st,_t3ed;
int calc(int h,int m,int s){return 3600*h+60*m+s;
}
bool check1(int T){if(t1st<=T && T<=t1ed) return true;if(_t1st<=T && T<=_t1ed) return true;return false;
}
bool check2(int T){if(t2st<=T && T<=t2ed) return true;return false;
}
bool check3(int T){if(t3st<=T && T<=t3ed) return true;if(_t3st<=T && T<=_t3ed) return true;return false;
}
void solve(){t1st=calc(7,0,0),t1ed=calc(9,0,0);_t1st=calc(18,0,0),_t1ed=calc(20,0,0);t2st=calc(11,0,0),t2ed=calc(13,0,0);t3st=calc(22,0,0),t3ed=calc(23,59,59);_t3st=calc(0,0,0),_t3ed=calc(1,0,0);int n,Y,M;cin>>n>>Y>>M;set<string> st1,st2,st3;for(int i=1;i<=n;i++){string s1,s2,s3;cin>>s1>>s2>>s3;int y=stoi(s2.substr(0,4));int m=stoi(s2.substr(5,2));if(m!=M || y!=Y) continue;int _hour=stoi(s3.substr(0,2));int _minn=stoi(s3.substr(3,2));int _second=stoi(s3.substr(6,2));int _time=calc(_hour,_minn,_second);if(check1(_time)){st1.insert(s1);}if(check2(_time)){st2.insert(s1);}if(check3(_time)){st3.insert(s1);}}cout<<st1.size()<<" "<<st2.size()<<" "<<st3.size()<<endl;}
int main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T=1;while(T--) solve();return 0;
}
K.可以分开吗?
解题思路
- dfs,每次搜索一个联通块时,要注意将周围都白色方块计数,并且打上标记,标记的方法可以用map或者set记录,亲测重新再开一个vis数组每次清空会超时
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
using namespace std;
const int N=510;
typedef pair<int,int> PII;
char g[N][N];
int dx[4]={-1,0,1,0};
int dy[4]={0,1,0,-1};
bool vis[N][N];
bool vis2[N][N];
int n,m;
int ans=1e8;
int cnt=0;
void dfs(int x,int y,map<PII,int> &mp){vis[x][y]=1;for(int i=0;i<4;i++){int tx=x+dx[i];int ty=y+dy[i];if(tx<1 || tx>n || ty<1 || ty>m) continue;if(g[tx][ty]=='0'){if(!mp[{tx,ty}]){cnt++;mp[{tx,ty}]=1;}continue;}if(vis[tx][ty]) continue;dfs(tx,ty,mp);}
}
void init(){for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){vis2[i][j]=0;}}
}
void solve(){cin>>n>>m;for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){cin>>g[i][j];}}for(int i=1;i<=n;i++){for(int j=1;j<=m;j++){if(g[i][j]=='1' && !vis[i][j]){map<PII,int> mp;cnt=0;dfs(i,j,mp);ans=min(ans,cnt);}}}cout<<ans<<endl;
}
signed main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T=1;while(T--) solve();return 0;
}
D. 字符串里串
解题思路
- 找一个连续子串,和一个子序列,满足要求,贪心的想,从左往右看,若第i位字母在[i+1,n]中出现,则可以将[1,i]子串是满足条件的(我们可以将[1,i-1]作为一部分,后面出现的相同的字母作为第二部分,构成子序列),从右向左同理。
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){int n;cin>>n;string s;cin>>s;s=" "+s;map<char,int> mp;int ans=0;for(int i=n;i>=2;i--){if(mp[s[i]]) ans=max(ans,i);else mp[s[i]]=1;}map<char,int> mpp;for(int i=1;i<=n-1;i++){if(mpp[s[i]]) ans=max(ans,n-i+1);else mpp[s[i]]=1;}cout<<ans<<endl;
}
int main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T=1;while(T--) solve();return 0;
}
C. 字符串外串
解题思路
- 构造题,与D的想法类似,首先构造m部分,在字符串右边循环插入a-z,此时左端部分只能插入a-z这26种字母,因此无解条件为n-m>26 || n==m
- 因此统一构造方法,取(n-m)个字母节的循环,详细可以见官方题解的图
#include<bits/stdc++.h>
#define endl '\n'
using namespace std;
void solve(){int n,m;cin>>n>>m;if(n==m || n-m>26){cout<<"NO"<<endl;return;}string s;cout<<"YES"<<endl;for(int i=0;i<n;i++){char ch='a'+i%(n-m);s+=ch;}cout<<s<<endl;}
int main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;while(T--) solve();return 0;
}
H.一起画很大的圆!
解题思路
- guess题,猜错了,鏖战两小时未能战胜
- 外接圆半径最大,想到尽量让三个点接近一条直线,这样的话半径最大,则可以有两种方法构造,(b,d),(b-1,d),(a,d-1)或(a,d),(a,d-1),(a+1,c)比较一下即可
#include<bits/stdc++.h>
#define endl '\n'
#define int long long
#define double long double
using namespace std;
typedef pair<int,int> PII;double distance(double x1,double y1,double x2,double y2){double dx=x2-x1;double dy=y2-y1;return sqrt(dx*dx+dy*dy);
}
double radius(double x1, double y1,double x2, double y2,double x3, double y3)
{double a=distance(x1,y1,x2,y2);double b=distance(x2,y2,x3,y3);double c=distance(x3,y3,x1,y1);double s=abs(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2))/2;double r=(a*b*c)/(4.0*s);return r;
}void solve(){int a,b,c,d;cin>>a>>b>>c>>d;PII ans[4];int x1,y1,x2,y2,x3,y3;double maxn=0;double r=0;x1=b,y1=d;x2=b-1,y2=d;x3=a,y3=d-1;r=radius(x1,y1,x2,y2,x3,y3);if(r>maxn){maxn=r;ans[1]={x1,y1};ans[2]={x2,y2};ans[3]={x3,y3};}x1=a,y1=d;x2=a,y2=d-1;x3=a+1,y3=c;r=radius(x1,y1,x2,y2,x3,y3);if(r>maxn){maxn=r;ans[1]={x1,y1};ans[2]={x2,y2};ans[3]={x3,y3};}for(int i=1;i<=3;i++){cout<<ans[i].first<<" "<<ans[i].second<<endl;}
}
signed main(){std::ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);int T;cin>>T;while(T--) solve();return 0;
}