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)    收藏  举报

导航