2025牛客寒假算法基础集训营2 个人题解
#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;
}
解题思路
#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;
}
解题思路
- 题目要求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;
}
解题思路
- 一开始卡了很久,以为是精度问题,写了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;
}
解题思路
- 大模拟,可以通过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;
}
解题思路
- 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;
}
解题思路
- 找一个连续子串,和一个子序列,满足要求,贪心的想,从左往右看,若第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;
}
解题思路
- 构造题,与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;
}
解题思路
- 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;
}