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())-begin(在一个降序的数组中,查找第一个小于等于该数的下标)去查找这个数,这个数的左边第一个数即是答案,然后减掉b所在的位置下标即可得出结果即可

点击查看代码
#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   swj2529411658  阅读(17)  评论(0编辑  收藏  举报

相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5
点击右上角即可分享
微信分享提示