2025牛客寒假算法基础集训营2
A
没有4和7就可以
B
给一个数组,长度为n,找一个数比数组中一半的数都小的最大的数
无论n为奇数还是偶数(整除的特性)
D
牛可乐定义字符串 𝑠的可爱度 𝑘为这样的一个最大整数,使得存在长度为 𝑘的连续子串,a、长度为 k 的不连续子序列
b满足 ,a=b特别地,若不存在符合要求的 a,b,则可爱度为 0
现在,对于给定的字符串 s,求解其可爱度。
子串
为从原字符串中,连续的选择一段字符(可以全选、可以不选)得到的新字符串。
仅在本题中,不连续子序列,定义为至少由两段不相邻的非空子串构成。
solution:
贪心地来想,只要a串最后一个字符,在之后的字符出现过,那么就可以构造这样一个b串使得a=b
- attention: 那么这样反过来,那需考虑
#include<bits/stdc++.h>
using namespace std;
map<char,int> mp;
int n;
string s;
int main(){
cin>>n;
cin>>s;
int lens=s.length();
for(int i=0;i<lens;++i) mp[s[i]]++;
int ans=0;
for(int i=0;i<lens;++i){
mp[s[i]]--;
if(mp[s[i]]>0) ans=max(ans,i+1);
}
for(int i=0;i<lens;++i) mp[s[i]]++;
reverse(s.begin(),s.end());
for(int i=0;i<lens;++i){
mp[s[i]]--;
if(mp[s[i]]>0) ans=max(ans,i+1);
}
cout<<ans<<endl;
return 0;
}
C
C和D是相反的,C考虑如何构造一个长度为n字符串s使得可爱度等于m
和D反过来想,我们直接地任意构造前m个字符串,但是最后n-m个字符一定满足同时
据此 因为最多有26个字母不同
但是如果我们只正向考虑,那么反过来找可爱度就会很大,所以也要考虑前n-m个数也要满足刚刚的条件,这时也需要满足上述条件,至于中间的2*m-n个数与相同即可
这时考虑一点:当时,,所以要及时停止输出
还有一点,容易得到n==m肯定无解
#include<bits/stdc++.h>
using namespace std;
int t;
int n,m;
void solve(){
cin>>n>>m;
if(n==m||m<n-26){
puts("NO");
return ;
}
puts("YES");
string ans;
int cnt=0;//记录构造的字符串多长
for(int i=1;i<=n-m;++i,++cnt)
cout<<char('a'+(i-1)%(n-m));
for(int i=1;i<=2*m-n;++i,++cnt)
cout<<char('a'+n-m-1);
for(int i=1;i<=n-m && cnt<=n;++i,++cnt)
if(cnt==n) break;//超过长度就结束
else cout<<char('a'+(i-1)%(n-m));
cout<<endl;
return ;
}
int main(){
cin>>t;
while(t--){
solve();
}
return 0;
}
还有一种构造方式
for (int i = 0; i < n; i++) {
cout << (char)('a' + i % (n - m));
}
F
通过这个位运算表达式,可以知道只有,同一位都是0,才取0,否则都为1
所以只有x=y时,表达式成立
(注意数据范围)
#include<bits/stdc++.h>
using namespace std;
int t;
long long l,r;
int main(){
cin>>t;
while(t--){
cin>>l>>r;
cout<<(long long )r-l+1<<endl;
}return 0;
}
G
设添柴火的次数为x,由题
(次数一定大于等于1)
取对数
得到
#include<bits/stdc++.h>
using namespace std;
int n,m;
int t;
int quick_pow(int a,int b){
if(b==0) return 0;
int base=a;
int ans=1;
while(b){
if(b&1) ans*=base;
base*=base;
b>>=1;
}return ans;
}
void solve(){
int ans=1;
cin>>n>>m;
if(m==1 || m>2*n){
puts("1");
return ;
}
long double l=log(n)/log(m)-1;
long double r=log(n)/log(m);
int dis=1e9;
int x=r;
for(int i=x-2>0?x-2:0;i<=x+2;++i){
if(abs(n-quick_pow(m,i))<dis){
ans=i;
dis=abs(n-quick_pow(m,i));
}
}
cout<<ans<<endl;
return ;
}
int main(){
cin.tie(0);
cout.tie(0);
cin>>t;
while(t--){
solve();
}
return 0;
}
J
纯模拟,注意细节,时间段是闭区间
代码给出了不好的示范
其实可以考虑用scanf输入,可以很好的把时间扣出来
#include<bits/stdc++.h>
using namespace std;
int n;
string h,m;
const int maxn=1e5+10;
map<string,bool> mp[4];
int ans[5];
void solve(){
cin>>n>>h>>m;
memset(ans,0,sizeof(ans));
mp[1].clear();
mp[2].clear();
mp[3].clear();
if(m.size()==1) m='0'+m;
for(int i=1;i<=n;++i){
string id,date,time;
cin>>id>>date>>time;
string year,month;
for(int j=0;j<=6;++j){
if(j<4) year+=date[j];
if(j>4) month+=date[j];
}
if(year!=h || month!=m) continue;
int hh=(time[0]-'0')*10+time[1]-'0';
int h3=(time[3]-'0')*10+time[4]-'0';
int h4=(time[6]-'0')*10+time[7]-'0';
if((hh>=7 && hh<9)||(hh>=18 && hh<20)||(hh==9 &&h3==0 && h4==0)||((hh==20 &&h3==0 && h4==0))){
if(mp[1][id]) continue;
mp[1][id]=1;
ans[1]++;
}
else if((hh>=11&&hh<13)||((hh==13 &&h3==0 && h4==0))){
if(mp[2][id]) continue;
mp[2][id]=1;
ans[2]++;
}
else if(hh>=22 || hh<1 || (hh==1 &&h3==0 && h4==0)){
if(mp[3][id]) continue;
mp[3][id]=1;
ans[3]++;
}
}
for(int i=1;i<=3;++i) cout<<ans[i]<<" ";
return ;
}
int main(){
cin.tie(0);
cout.tie(0);
int t=1;
while(t--){
solve();
}
return 0;
}
K
基础的dfs,对于一个连通块,找边界有多少块相邻的瓷砖
#include<bits/stdc++.h>
using namespace std;
int n,m;
const int maxn=510;
bool mp[maxn][maxn];
bool book[maxn][maxn];
int ans=maxn*maxn;
int cnt=0;
int nt[5][3]={{1,0},{0,1},{0,-1},{-1,0}};
void dfs(int i,int j){
if(i<1 || i>n || j<1 || j>m ) return ;
if(mp[i][j]==0){
++cnt;
return ;
}
for(int x=0;x<4;++x){
int ni=i+nt[x][0];
int nj=j+nt[x][1];
if(book[ni][nj]) continue;
book[ni][nj]=1;
dfs(ni,nj);
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;++i){
string s;cin>>s;
for(int j=1;j<=m;++j)
mp[i][j]=s[j-1]-'0';
}
for(int i=1;i<=n;++i)
for(int j=1;j<=n;++j){
if(book[i][j]==0 && mp[i][j]==1){
cnt=0;
dfs(i,j);
ans=min(ans,cnt);
}
}
cout<<ans<<endl;
return 0;
}
E
一个数组,给定区间,可以对,使得
而且+1,-1会在操作后清空
很容易地贪心地想,如果我们给最左端+x,那么一定到某个数时,一定可以使条件满足
我们设前缀和f,即需要满足
由于是+1后会清空,所以可以用静态查找最大值,用ST表
#include<bits/stdc++.h>
using namespace std;
#define ll long long
int n,q;
const int maxn=2e5+10;
int lg[maxn];
ll st[maxn][40];
ll f[maxn];
ll d[maxn];
void fun_st(){
for(int j=1;j<=lg[n];++j)//区间长度
for(int i=1;i<=n-(1<<j)+1;++i){
st[i][j]=max(st[i][j-1],st[i+(1<<(j-1))][j-1]);
}
}
int main(){cin.tie(0);cout.tie(0);
cin>>n>>q;
lg[1]=0;
for(int i=2;i<=maxn;++i) lg[i]=lg[i>>1]+1;
for(int i=1;i<=n;++i){
int x;cin>>x;
f[i]=f[i-1]+x;
d[i]=x-f[i-1];
st[i][0]=d[i];
}
fun_st();
while(q--){
int l,r;
cin>>l>>r;
if(l==r) {
cout<<0<<"\n";
continue;
}
int t=lg[r-(l+1)+1];
ll cnt=max(st[l][t],st[r-(1<<t)+1][t]);
ll ans=max(cnt+f[l-1],0ll);
cout<<ans<<endl;
}
}
本文作者:归游
本文链接:https://www.cnblogs.com/guiyou/p/18690375
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步