蓝桥杯校赛

个人感觉

星期六早上的校赛,八道题目都是以前出过的,三道考了全排列!!
直接看题目的话
第一题福尔摩斯密码没读懂,考完试想了想是哈希表
第二题蚂蚁一看就很复杂就先不做了(一般这种题目想出来要花很多时间,不值得,决定回头再做)
然后其它题目稍微有一点复杂,但是冷静下来理清思路就行了,12:30考试结束,我只写了5题(其中间隔字母和最大数我没有考虑周全),其中转向那道题脑子有一点混乱,今晚测试的时候发现有一些案例不能通过,改好之后就行了
然后我觉得最后一题,给数字和加减符号还有括号求最大数,我觉得那个括号根本没有必要,因为乘法有交换律,每次都选最大的两个数相加,再相减就行了。
最后一题是我没有考虑周全 orz,有括号的时候要额外判断
下面写代码

题目和代码

密码匹配

后面想了想写了出来

#include<bits/stdc++.h>
using namespace std;
long long int sum=0;

int main()
{
	//最长串 
	string str;
	cin>>str;
	int n;
	cin>>n;
	int ans=0;
	for(int i=0;i<n;i++)
	{
		string temp;
		cin>>temp;
		//注意初始化
		int mpm[26]={0};
		for(int i=0;i<temp.size();i++)
		{
			mpm[temp[i]-'a']++;
		}
		int index=0;
		while(index+8!=str.size()+1)
		{
			bool ok=true;
			int mps[26]={0};
			for(int i=index;i!=index+8;i++)
			{
				mps[str[i]-'a']++;
			}
			for(int i=0;i<26;i++)
			{
				if(mps[i]!=mpm[i])
				{
//					cout<<mps[i]<<" "<<mpm[i]<<endl;
					ok=false;
					break;
				}
			}
			if(ok)ans++;
			
			index++;
		}
	}
	cout<<ans;
}

蚂蚁

思维题,没想明白
https://blog.csdn.net/wr132/article/details/50791505

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int num[60];
	int n;
	cin>>n;
	vector<int>lfnum;
	vector<int>rfnum;
	int L=0,R=0;
	int start=0;
	int f=0;
	for(int i=0;i<n;i++)
	{
		cin>>num[i];
		if(i==0)
		{
			start=num[i];
			if(start>0) f=1;
			else f=-1;
			continue;
		}
		if(num[i]>0&& abs(num[i]) <abs(start) )
		{
			L++;
		}
		if(num[i]<0&&abs(num[i])>abs(start))
		{
			R++;
		}

	}
	if((f==1&&R==0)||(f==-1&&L==0))
	{
		cout<<1;	
	}
	else cout<<R+L+1;
//	 cout<<R+L+1;
	
} 

稍大的串

串可以按照字典序进行比较。例如:
abcd 小于 abdc
如果给定一个串,打乱组成它的字母,重新排列,可以得到许多不同的串,在这些不同的串中,有一个串刚好给定的串稍微大一些。科学地说:它是大于已知串的所有串中最小的串。你的任务就是求出这个“稍大的串”。
样例输入:
输入串:
abfxy
样例输出:
abfyx
样例输入:
输入串:
ayyyxxff
样例输出:
fafxxyyy
数据规模约定:
输入的串不超过1000个字符。
特例:
如果已知的串已经是所有重组串中最大的,则原样输出读入的那个串。
这道题很明显就是考全排列啊 不会写直接GG了,我当时就是忘了怎么写,还好查了标准库想起来上星期发现的next_permutation(),下次全排列的递归想不出来背也要背出来

#include<bits/stdc++.h>
using namespace std;
//vts sort后的所有序列 
vector<string> pvt;

void fun(string str)
{
	do
	{
		pvt.push_back(str);
	}while(next_permutation(str.begin(),str.end()));
}

bool cmp(string a,string b)
{
	return a<b;
}

int main()
{
	string str;
	cin>>str;
	//思路 对str进行sort,然后输出这个str的全排列,然后再按字典序排序,然后定位到原字符串
	//然后找它下一个字符串即可
	string temp_str=str;
	//排序读入的字符串 
	sort(temp_str.begin(),temp_str.end());
	//讲这个字符串的全排列添加到pvt中 
	fun(temp_str);
	//排序pvt 
	sort(pvt.begin(),pvt.end(),cmp);
//	for(int i=0;i<pvt.size();i++)
//	{
//		cout<<pvt[i]<<endl;
//	}
//	cout<<pvt.size()<<endl;
	int index=0;
	for(;index<pvt.size();index++)
	{
		if(pvt[index]==str) break; 
	}
	
	if(index==pvt.size()-1) cout<<str;
	else cout<<pvt[index+1];
}

转向

哎 写这道题的时候早上脑袋有点懵,没有演算,发现一些测试用例没通过,没办法

#include<bits/stdc++.h>
using namespace std;
int main()
{
	int a,b;
	cin>>a>>b;
	int ans;
	//正着走 
	int ansA;
	//反着走 
	int ansB;
	//无论大小 a和b永远有正着走和反着走 且它们的大小一定一样 只不过正负号不一样 
	//只处理a<b的情况 如果输入a>b 交换 并且修改接下来的正负号 
	bool flag=true;
	if(a>b)
	{
		swap(a,b);
		flag=false;	
	}
	if(a==b)
	{
		cout<<0;
	}
	else
	{
		ansA=-((a+360-b)%360);
		ansB=b-a; 
		//如果之前发生了交换 
		if(flag==false)
		{
			ansA=-ansA;
			ansB=-ansB;
		}
		
		//判断规则 
		if(abs(ansA)>abs(ansB))
		{
			cout<<ansB;
		}
		else if(abs(ansA)<abs(ansB))
		{
			cout<<ansA;
		}
		else
		{
			cout<<ansA>0?ansA:ansB;
		}
	}

//一些特殊的案例无法通过! 如181 180! 
//  	if(a>b)swap(a,b);
//	//从a到b可以走正的也可以走负的
//	//1.b-a 2.a-b
//	//1.180-70 -70-180
//	//45 270= 225 -135
//	int ansA=b-a;
//	//ansB= (a+x)%360=b
//	int ansB=-(360+(a-b));
//	cout<<ansA<<" "<<ansB<<endl;
//	if(abs(ansA)>abs(ansB)) cout<<ansB;
//	else if(abs(ansA)<abs(ansB)) cout<<ansA;
//	else printf("%d",ansA>0?ansA:ansB);
}

1-偏差数列

全排列 会就是会 不会也没办法

#include<bits/stdc++.h>
using namespace std;
vector<vector<int> > vtt;

int main()
{
	//对从1到n生成全排列
	//然后找符合 ni-i<=1 的序列 
	int n;
	cin>>n;
	vector<int> vt;
	for(int i=1;i<=n;i++) vt.push_back(i);		
	do
	{
		vtt.push_back(vt);
	}
	while(next_permutation(vt.begin(),vt.end()));

	int ans=0;
	for(int i=0;i<vtt.size();i++)
	{
		bool ok=true;
		for(int j=0;j<vtt[i].size();j++)
		{
			if(abs(vtt[i][j]-(j+1))>1)
			{
				ok=false;
				break;
			}
		}
		if(ok) ans++;
	}
	cout<<ans;
} 

递增数列

这道题我一开始想错了,但是后面思路很清晰又推出规律了,因为每次都选一个数放到最左边,那么我对数列中的每个数,将它们放到对应的位置即可。
每个数移动的次数就是它们对应位置的值。
比如说下面的数列

5 4 3 2 1
1 5 4 3 2 =>1 1移动到最左边 11 2 5 4 3 =>1+2 2 移动到最左边 1再移动到最左边 21 2 3 5 4 =>1+2+3 同理 31 2 3 4 5 =>1+2+3+4

注意每次移动要挪位置,不然对某些情况 会计算挪动的次数
应该是贪心的写法吧,不过我的代码好像会超时,对于10万个数据。。

#include<bits/stdc++.h>
using namespace std;
int main()
{
	vector<int> vt;
	int n;
	cin>>n;
	for(int i=0;i<n;i++)
	{
		int temp;
	 	cin>>temp;
		vt.push_back(temp);
	}
	int ans=0;
	for(int i=0;i<n;i++)
	{
		//如果该元素的不在对应位置 
		if(vt[i]!=i+1)
		{
			//找到这个元素的位置 
			int j=0;
			for(;j<vt.size();j++)
			{
				if(vt[j]==i+1) break;
			}
			//注意 k从找到的位置 一直到遍历中的i位置 依次覆盖值
			//我觉得这很有可能超时 但一时想不出更好的方法! 
			for(int k=j;k>=i;k--)
			{
				vt[k]=vt[k-1];
			}
			vt[i]=i+1;
			ans+=i+1;
			i=-1;
		}
	} 
	cout<<ans;
}


最大数

这道题我觉得是最蠢的,因为括号我觉得是没用的,加法有交换律,没必要加括号
事实证明我才是最蠢的
https://blog.csdn.net/yinxiaobao97/article/details/84672987 来源

#include<bits/stdc++.h>
#define maxn 150
using namespace std;
int n,p,q,k;
int a[maxn];
bool cmp(int x,int y){
	return x>y;
}
int main(){
	cin>>n>>p>>q>>k;
	//从1开始读入 
	for(int i=1;i<=n;i++) cin>>a[i];
	//从大到小排 
	sort(a+1,a+1+n,cmp);
	int ans=0;
//	4,3,2,1 :
//2个减号 1个加号 一个括号 最大为:4-(1-2)+3  
//2个减号 1个加号 两个括号时:(4-(1-2))+3
//3个减号 1个括号:4-(1-2-3) 两个括号时:(4-(1-2-3))
//无论如何上面结果都是8
//所以有括号的时候,始终是前n-1大的数减去最小的那个数 
	if(k==0||q==0){
		for(int i=1;i<=n;i++){
			//如果加好没用完,直接相加 
			if(i<=p+1) ans+=a[i];
			//加号用完了 相减 
			else ans-=a[i];
		}
	}
	else{
		for(int i=1;i<n;i++) ans+=a[i];
		ans-=a[n];
	}
	cout<<ans<<endl;
	return 0;
}

间隔字母

这道题挺有意思的,但是我因为太久没写算法 迭代器都忘记怎么写了 ? 弄了好久才知道是
map<char,int>::iterator 一直写反了,后面存到map的时候又直接存数组的下标,弄了好久。事实证明写题目不能停啊!!!
注:
少处理一种情况。。还是错的,答案参考 https://www.cnblogs.com/Patt/p/5672220.html

#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
map<char,int> mp;
bool judge(int num)
{
	map<char,int>::iterator it;
	for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
	{
		if(it->second>(num-1)/2+1) return false;
	}
	return true;
}
int main()
{
	//想法错了 这道题要用贪心,我没有考虑到
	//abcabc => abacbc
	//这种情况 会漏掉一些答案。
	//同时 选择字符放置的时候也要判断接下来够不够放,不够的话就要换大一点的字符放 
	string str;
	cin>>str;

	int count=str.size();
	for(int i=0;i<str.size();i++)
	{
		mp[str[i]]++;
	}
	map<char,int>::iterator it;
	string ans="";
	char pre=' ';
	for(int i=0;i<str.size();i++)
	{
		for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++)
		{
			if(it->second&&it->first!=pre)
			{
				//这里默认选择这个字符
				it->second--;
				//如果剩下的字符合格,则放入这个字符
				if(judge(count-1))
				{
					ans+=it->first;
					pre=it->first;
					count--;
					break;
				}
				//如果不合格 则恢复它的次数
				else it->second++;
			}
		}
	}
	cout<<ans;
}


  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值