0401-0412题解反思
知识点模块
1.字符串也可以进行整理,如abbbba,sort以后会被整理为aabbbb
sort(s.begin(),s.end());
2.获取子串可以使用substr函数
s.substr(i,8)//从i位置起获取长度为8的子串
3.同余定理的使用
当a%k= b%k的时候 (a-b)%k==0
4.二维双端队列的使用deque
deque<int>de[N]
常见的操作有
de.push_back() de.pop_back()
de.push_front() de.pop_front()
5.时间的获取
当我们把时间的单位化为秒的时候
h=总秒数/3600 min=总秒数%3600/60 s=总秒数%60
牛客周赛 Round 39
小红不想做鸽巢原理
这一题我们注意到两个要求,一个是我们每次只能取k个并且要让最后的小球数量小于k个,一个是我们要让最后剩下的球的颜色种类是最小的,那么本质上其实就是一道贪心的题目,要让最后的小球数量少于k,那么总数只有减去d=sum/k*k,于是我们记录一下小球的前缀和,当S[i]<d,说明这个种类可以完全被减掉,看代码理解理解
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n,k,sum=0;
cin>>n>>k;
vector<int>ve(n+1),s(n+1);
for(int i=1;i<=n;i++){
cin>>ve[i];
sum+=ve[i];
}
if(sum%k==0){
cout<<"0";
return;
}
sort(ve.begin()+1,ve.end());//从小到大排,实现贪心
for(int i=1;i<=n;i++)
{
s[i]=s[i-1]+ve[i];
}
int d=sum/k*k;//当sum减去d时会满足sum-d<k
int ans=n;
for(int i=1;i<=n;i++)
{
if(s[i]<=d) ans--;
}
cout<<ans;
}
signed main(){
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
小红不想做完全背包(easy)
因为规定了p=3,那么每个数去取余3的只会有0 1 2这三个余数,我们在0 1 2这三个余数思考,题目是确保有答案的,那么在0 1 2中要出现3的倍数,只有3个1,3个2,1和2,那么直接枚举就可以了
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
int dp[1005][1005],val[1005],w[1005];
void solve()
{
int n,m;
cin>>n>>m;
vector<int>ve(n+1);
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
if(x%3==0){
cout<<1;
return;
}
else ve[x%3]++;
}
if(ve[1]!=0&&ve[2]!=0) cout<<2;
if(ve[1]!=0&&ve[2]==0) cout<<3;
if(ve[1]==0&&ve[2]!=0) cout<<3;
}
signed main(){
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
蓝桥杯补题
记得开longlong 记得开longlong 记得开longlong
P8630 [蓝桥杯 2015 国 B] 密文搜索
首先我们运用上述的知识点,字符串也是可以sort整理成字典序的,那么当我们从左往右遍历8个长度的字符串时,用substr函数获取子串,然后整理,再根据mp中记录过的整理过的子串值,结果加上这个值即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
string s;
cin>>s;
int n;
map<string,int>mp;
cin>>n;
for(int i=1;i<=n;i++)
{
string sb;
cin>>sb;
sort(sb.begin(),sb.end());
mp[sb]++;
}
int cnt=0;
for(int i=0;i<s.size()-7;i++)
{
string st=s.substr(i,8);//从位置i开始获取长度为8的子串
sort(st.begin(),st.end());
cnt+=mp[st];
}
cout<<cnt;
}
signed main(){
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
P8649 [蓝桥杯 2017 省 B] k 倍区间
我们首先利用知识点3,就是同余定理的使用,记录一下前缀和,然后开一个余数数组,记录一下每一个余数到底有多少个,一个余数出现了n次,那么对应的区间就有n个中选2个,累计输出答案即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
void solve()
{
int n,k;
cin>>n>>k;
vector<int>s(n+1),y(n+1);
for(int i=1;i<=n;i++)
{
int x;
cin>>x;
s[i]=s[i-1]+x;//前缀和
}
for(int i=0;i<=n;i++)
{
y[s[i]%k]++;
}
int ans=0;
for(int i=0;i<=k;i++)
{
ans+=(y[i]-1)*(y[i])/2;
}
cout<<ans;
}
signed main(){
int t=1;
//cin>>t;
while(t--) solve();
return 0;
}
P8661 [蓝桥杯 2018 省 B] 日志统计
这一题我们要使用一个二维的单调队列,对应我们的知识点4,首先构造一个结构体来存ts和id,按照时间从小到大排序,时间相同按序号小的先排,然后在每一个对应序号的deque中存入我们的时间,每存入一个时间都要和队首的时间比较一下,如果这段差值大于d,那么就要把队头舍弃掉,想象一下如同一个滑动窗口,最后我们检查一下队列中的size有没有大于k即可,开一个ans数组,符合条件的标记为1,最后按序输出即可
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e5+5;
bool ans[N];
struct node{
int ts,id;
}a[N];
bool cmp(node x,node y)
{
if(x.ts!=y.ts) return x.ts<y.ts;
return x.id<y.id;
}
deque<int>q[N];
void solve()
{
int n,d,k,maxx=0;
cin>>n>>d>>k;
for(int i=0;i<n;i++){
cin>>a[i].ts>>a[i].id;
maxx=max(maxx,a[i].id);
}
sort(a,a+n,cmp);
for(int i=0;i<n;i++)
{
int pos=a[i].id;
int g=a[i].ts;
q[pos].push_back(g);
while(!q[pos].empty()&&g-q[pos].front()>=d) q[pos].pop_front();
if(q[pos].size()>=k) ans[pos]=1;
}
for(int i=0;i<100005;i++){
if(ans[i]) cout<<i<<endl;
}
}
signed main(){
int t=1;
while(t--) solve();
return 0;
}
P8665 [蓝桥杯 2018 省 A] 航班时间
这一题洛谷的题解我是有点看不懂的,但是后面想明白了,每一次输入两次数据,每一次的第二个时间-第一个时间我们称为假想去程时间,我们可以从题意开始理解,假设北京时间为10点,上午12点到达美国,两地的时差为12小时,那么实际的飞行时间为,12-10+12=14,为什么是这么想呢?因为美国到达时间-时差=中国的到达时间,而中国的到达时间-中国的出发时间=飞行时间,而我们每次输入的数据第一行为中国的出发时间k1 美国的到达时间k2;那么k2-sc(时差)-k1=x(飞行时间);第二行则为美国的出发时间k3和中国的到达时间k4;那么k4+sc-k3=x;那么令k2-k1=t1,k4-k3=t2,则有x=(t1+t2)/2
这一题的输入格式也是挺值得学习的,如果结尾有空格即getchar()==" ",那么进行scanf("(+%d)",&d);就可以了
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int tim()
{
int h1,h2,m1,m2,s1,s2,d=0;
scanf("%d:%d:%d %d:%d:%d",&h1,&m1,&s1,&h2,&m2,&s2);
if(getchar()==' '){
scanf("(+%d)",&d);
}
return (86400*d+3600*h2+60*m2+s2)-(3600*h1+60*m1+s1);
}
signed main()
{
int t;
cin>>t;
while(t--)
{
int g=(tim()+tim())/2;
printf("%02d:%02d:%02d\n",g/3600,g%3600/60,g%60);
}
return 0;
}
posted on 2024-04-14 22:53 swj2529411658 阅读(32) 评论(0) 收藏 举报
浙公网安备 33010602011771号