0219-0223部分题解和思路
VJ第五次选拔赛
A题 Triple Metre
这一题的本质就是寻找题给的字符串中的子串,看有没有与其符合的子串,虽然题目给的很吓人T=10^5个oxx,但是注意The length of S is between 1 and 10 (inclusive)这句话”,也就是我们让T=10个以上的oxx就可以了,然后就是熟悉的查找子串的方法了
点击查看代码
#include <bits/stdc++.h> using namespace std; bool cz(string&s1,string&s2) { size_t pos=s1.find(s2); if(pos!=std::string::npos) return true; else return false; } void solve() { string s1="oxxoxxoxxoxxoxxoxxoxxoxxoxxoxxoxxoxxoxx",s2; cin>>s2; if(cz(s1,s2)) cout<<"Yes"; else cout<<"No"; } int main() { int t=1; while(t--) { solve(); } return 0; }
B题 Counting 2
思路很简单就是找有几个大于x的数,但是数据范围不小,所以用lower_bound来查找第一个大于等于它的数,然后n-k(第一个大于等于他的数的下标)即可,这样便不会超时
点击查看代码
#include <bits/stdc++.h> using namespace std; const int N=2e5+5; int a[N],n,t; void solve() { int x; cin>>x; int k=lower_bound(a,a+n,x)-a; cout<<n-k<<endl; } int main() { cin>>n>>t; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n);//整理成升序数组 while(t--) { solve(); } return 0; }
E题Sum of difference
这题需要用数学知识分析一下详见下图
代码来啦
点击查看代码
#include <bits/stdc++.h> using namespace std; const int N=2e5+5; typedef long long ll; ll a[N],sum[N],ans; void solve() { int n; cin>>n; for(int i=1;i<=n;i++){ cin>>a[i]; } sort(a+1,a+n+1,greater<ll>());//整理完在搞前缀和 for(int i=1;i<=n;i++) { sum[i]=sum[i-1]+a[i]; } for(int i=1;i<=n;i++) { ans+=sum[n-i]-sum[n]+sum[i]; } cout<<ans; } int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t=1; while(t--){ solve(); } return 0; }
L题Triangles
这题其实也需要分析一下,我们先把输入的数弄成一个升序的数组,保证取a>b>c,因为a+b>a+c>c,而且a+c>b+c>b,所以只需要满足b+c>a即可,由于我们枚举取a,b,所以只要c尽量大就可以符合题意,通过二分来查找这个满足题意的最小c的值,只需要每次lower_bound查找第一个小于等于a-b的数即可,用 lower_bound(begin,end,c,greater
点击查看代码
#include <bits/stdc++.h> using namespace std; const int N=2e3+5; typedef long long ll; ll a[N],ans; void solve() { int n; cin>>n; for(int i=0;i<n;i++) cin>>a[i]; sort(a,a+n,greater<ll>());//数列是单调递减的 for(int i=0;i<=n-3;i++)//i停留在倒数第3个数 { for(int j=i+1;j<=n-2;j++)//j停留在倒数第二个数 { ll x=a[i]-a[j]; int k=lower_bound(a,a+n,x,greater<ll>())-a; if(k-1>j) ans+=k-j-1;////m-1>j说明这个区间有比x大的值 } } cout<<ans; } int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t=1; while(t--){ solve(); } return 0; }
K题Colorful Candies
这题就是求长度为k的区间总共最多有几类糖果,但是这个区间的数是可以重复的,所以把它当成一个活动的滑块,当滑块离开了这个点,对应的哈希值减一即可,然后输出最大种类数就行
点击查看代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e5+5; ll a[N],s[N]; ll res; void solve(){ int n,k; map<ll,ll> mp; cin>>n>>k; for(int i=0;i<n;i++) cin>>a[i]; for(int i=0;i<n;i++) { mp[a[i]]++; if(i>=k-1){//i-1-k>0就是滑块开始形成的条件 res=max(res,(ll)mp.size()); mp[a[i-k+1]]--;//滑块开始离开这个点,这个点就-1; if(mp[a[i-k+1]]==0) mp.erase(a[i-k+1]); } } cout<<res; } int main() { int t=1; while(t--) { solve(); } return 0; }
F题Unlucky 7
这题涉及到进制转换的知识点,还有利用to_string函数去找到含有数字7的数有几个,但是注意八进制和十进制的计数可能会存在重复因此需要标记一下
十进制转换到其他进制的三行代码
ostringstream oss;
oss<<oct<<i;
int k=stoi(oss.str());
题解代码
点击查看代码
#include <bits/stdc++.h> #include <sstream> using namespace std; const int N=1e5+10; int a[N],b[N],cnt; bool st[N]; bool check(int x) { string m; m=to_string(x); for(int i=0;i<m.size();i++) { if(m[i]=='7') return true;//找到含7的数字计数,最后用n减掉即可 } return false; } void solve() { int n; string m; cin>>n; for(int i=1;i<=n;i++) { if(check(i)&&!st[i]){ st[i]=1; cnt++; } } for(int i=1;i<=n;i++) { ostringstream oss; oss<<oct<<i; int k=stoi(oss.str()); if(check(k)&&!st[i]) { cnt++; } } cout<<n-cnt; } int main() { int t=1; while(t--) { solve(); } return 0; }
VJ第六次选拔赛
B题Jiubei and Overwatch
这题其实就是模拟,但是要直切要害,找到最大值然后分类讨论max1<=kx与max1>kx的情况
点击查看代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; void solve() { ll n,m,x,y,a,b,c,k,max1=0,t; cin>>n>>k>>x>>y; while(n--) { cin>>a; max1=max(a,max1); } b=ceil(1.0*max1/x); c=max1-k*x; if(b>k){ t=ceil(1.0*c/y)+k; } else{ t=ceil(1.0*max1/x); } cout<<t<<endl; } int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t=1; cin>>t; while(t--) { solve(); } return 0; }
F题Sum of Numerators
我们可以这样的思考n和k的关系
1 2 3 4 5 6 7 8
当k=1时,会变成
1 1 3 2 5 3 7 4
当k=2时,会变成
1 1 3 1 5 3 7 2
由此观察可以发现当k=0时,res=8(1+8)/2=36;
当k=1时,1-n的偶数2 4 6 8除以2,res-=4(1+4)/2,res=26;
当k =2时 1-n/2的偶数2 4除以2,res-=2*(1+2)/2,res=23;
由此类推 当k=0或n/2=0时res就不变了
点击查看代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; void solve() { ll n,k,res; cin>>n>>k; res=n*(1+n)/2; while(n&&k) { n/=2; k--; res-=n*(1+n)/2; } cout<<res<<endl; } int main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); int t=1; cin>>t; while(t--) { solve(); } return 0; }
L题Monster Tower
首先就是答案具有单调性,所以可以使用二分来,然后验证每个值;使用一个优先队列,先存入k层以及k层以下的的值,然后写一个清空函数,当mid>=x的时候,这个值就可以删掉,如果删不掉就再存进去,经过几次以后,最后检查优先队列(堆)是不是空的
点击查看代码
#include <bits/stdc++.h> using namespace std; typedef long long ll; priority_queue<ll,vector<ll>,greater<ll> >q;//俗称堆,最小的元素在上面 const int N=2e5+5; ll a[N],n,m,k; ll kill(ll mid){//用来清空,先取出来,不满足的放回去,满足的扔掉; while(q.size()){ ll x=q.top(); q.pop(); if(mid>=x) mid+=x; else{ q.push(x); return mid; } } return mid; } bool check(ll mid) { while(q.size()) q.pop();//先把队列清空; for(int i=1;i<=k;i++){ q.push(a[i]); } for(int i=k+1;i<=n;i++) { ll nx=kill(mid); if(q.size()>=k) return 0;//如果进行一次没办法清完的话,说明这个mid是不满足要求的,就返回fasle; else { q.push(a[i]); mid=nx; } } ll nx=kill(mid);//当i=n的时候,a[n]这个点还没放进去,这一步用来处理a[n]; if(q.size()) return 0; return 1;//说明清空完了,就是对的 } void solve() { cin>>n>>k; for(int i=1;i<=n;i++) cin>>a[i]; ll l=0,r=1e9; while(l<r){ //二分模板 右边是正确的左边是错误的 所以这么更新 ll mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } cout<<l<<"\n"; } signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t; cin>>t; while(t--) { solve(); } return 0; }
C题 Ah, It's Yesterday Once More
理解一下题意,输出以n开头的序列即可
2024牛客寒假算法基础集训营6
A题宇宙的终结
三个不同素数的乘积在100以内的有30 42 66 70 78,那就很朴素的if else了
点击查看代码
#include <bits/stdc++.h> using namespace std; void solve() { int l,r; cin>>l>>r; if(l<=30&&r>=30) cout<<"30"; else if(l<=42&&r>=42) cout<<"42"; else if(l<=66&&r>=66) cout<<"66"; else if(l<=70&&r>=70) cout<<"70"; else if(l<=78&&r>=78) cout<<"78"; else cout<<"-1"; } signed main() { int t=1; while(t--) { solve(); } return 0; }
C题心绪的解剖
看的韦学姐的做法,先用三层for暴力打印出以三个斐波那契列数可能的和作为键,然后以三个数字作为值的哈希表,然后这样就可以避免超时
关键代码
map<int,vector<int> >mp;
vector<int>g(3)
mp[(三个斐波那契列数字的和)]=g
点击查看代码
#include <bits/stdc++.h> using namespace std; void solve() { int n; vector<int>ve(200); ve[1]=0,ve[2]=1; map<int,vector<int> > mp; for(int i=3;i<=45;i++) ve[i]=ve[i-1]+ve[i-2];//开到第45个,因为第45个为701408733; for(int i=1;i<=45;i++) for(int j=1;j<=45;j++) for(int m=1;m<=45;m++){ vector<int>g(3); int a=ve[i]+ve[j]+ve[m]; g[0]=ve[i],g[1]=ve[j],g[2]=ve[m]; if(a>1e9) continue; if(!mp.count(a)) mp[a]=g;//map的每个值存了三个数 } //通过一次三层for先把三个数字所可以得到的和作为键,把这三个数字作为值,避免了多次的for循环导致超时 int q,k; cin>>q; while(q--) { cin>>k; if(mp.count(k)){ vector<int> g=mp[k]; for(auto v:g) cout<<v<<" "; cout<<"\n"; } else cout<<-1<<"\n"; } } signed main() { ios::sync_with_stdio(0),cin.tie(0),cout.tie(0); int t=1; //cin>>t; while(t--) { solve(); } return 0; }
D题友谊的套路
分两种情况,一种是小红让二追三了,一种是小红被让二追三了,那就很简单了
点击查看代码
#include <bits/stdc++.h> using namespace std; void solve() { double x; cin>>x; //两种情况 小红让二追三 小红被让二追三 double p=(1-x)*(1-x)*x*x*x+x*x*(1-x)*(1-x)*(1-x); printf("%.7lf",p); } int main() { int t=1; while(t--) { solve(); } return 0; }
posted on 2024-02-25 02:53 swj2529411658 阅读(17) 评论(0) 编辑 收藏 举报
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧