蓝桥杯——2018第九届C/C++真题[省赛][B组]

目录

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第1张图片第几天

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第2张图片明码

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第3张图片乘积尾零

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第4张图片测试次数

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第5张图片快速排序

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第6张图片递增三元组

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第7张图片螺旋折线 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第8张图片 日志统计

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第9张图片全球变暖 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第10张图片乘积最大 


 

第几天

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第11张图片

思路:这道题是蓝桥杯爱考的老题了,咱们可以通过电脑自带的计算器做也可以用excel做,最后我再提供一下代码吧

计算器

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第12张图片

excel

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第13张图片  

代码:我把计算各种日期问题的模板代码放在这里,大家可以练习练习

#include
using namespace std;
class Date {
public:
	int GetMonthDay(int year, int month) const
	{
		static int monthDayArray[13] = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
		int day = monthDayArray[month];
		// 365天 5小时+
		if (month == 2 && ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)))
		{
			day += 1;
		}

		return day;
	}

	Date(int year, int month, int day)
	{
		_year = year;
		_month = month;
		_day = day;

		if (!(_year >= 0
			&& (month > 0 && month < 13)
			&& (day > 0 && day <= GetMonthDay(year, month))))
		{
			cout << "非法日期->";
			// this->Print();
			Print();
		}
	}

	void Print() const
	{
		cout << _year << "-" << _month << "-" << _day << endl;
	}

	bool operator>(const Date& d)  const
	{
		if (_year > d._year)
		{
			return true;
		}
		else if (_year == d._year && _month > d._month)
		{
			return true;
		}
		else if (_year == d._year && _month == d._month && _day > d._day)
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	// d1 == d2
	bool operator==(const Date& d)  const
	{
		return _year == d._year
			&& _month == d._month
			&& _day == d._day;
	}

	// d1 < d2
	bool operator<(const Date& d)  const
	{
		return !(*this >= d);
	}

	// d1 >= d2
	bool operator>=(const Date& d)  const
	{
		return *this > d || *this == d;
	}

	bool operator<=(const Date& d)  const
	{
		return  !(*this > d);
	}

	bool operator!=(const Date& d)  const
	{
		return  !(*this == d);
	}

	// d1 += 100 
	Date& operator+=(int day)
	{
		if (day < 0)
		{
			return *this -= -day;
		}

		_day += day;
		while (_day > GetMonthDay(_year, _month))
		{
			_day -= GetMonthDay(_year, _month);
			++_month;

			if (_month == 13)
			{
				_month = 1;
				_year++;
			}
		}

		return *this;
	}

	// d1 + 100
	Date operator+(int day)  const
	{
		Date ret(*this);
		//ret.operator+=(day);
		ret += day;

		return ret;
	}

	// d1 -= 10
	Date& operator-=(int day)
	{
		if (day < 0)
		{
			return *this += -day;
		}

		_day -= day;
		while (_day <= 0)
		{
			--_month;
			if (_month == 0)
			{
				--_year;
				_month = 12;
			}

			_day += GetMonthDay(_year, _month);
		}

		return *this;
	}

	// d1 - 10
	Date operator-(int day)  const
	{
		Date ret(*this);
		ret -= day;

		return ret;
	}

	// ++d1;
	Date& operator++()
	{
		*this += 1;

		return *this;
	}
	// d1++; 后置为了跟前置++,进行区分
	// 增加一下参数占位,跟前置++,构成函数重载
	Date operator++(int)
	{
		Date ret(*this);
		*this += 1;

		return ret;
	}

	// --d1;
	Date& operator--()
	{
		*this -= 1;
		return *this;
	}

	Date operator--(int)
	{
		Date ret(*this);
		*this -= 1;
		return ret;
	}

	// offerDay - today
	int operator-(const Date& d)  const
	{
		Date max = *this;
		Date min = d;
		int flag = 1;

		if (*this < d)
		{
			max = d;
			min = *this;
			flag = -1;
		}

		int count = 0;
		while (min != max)
		{
			++min;
			++count;
		}

		return count * flag;
	}
private:
	int _year;
	int _month;
	int _day;
};
int main()
{
	Date d1(2000, 1, 1);
	Date d2(2000, 5, 4);
	int count = d2 - d1;
	cout << count << endl;
	return 0;
}

答案:125 

明码

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第14张图片

4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0
16 64 16 64 34 68 127 126 66 -124 67 4 66 4 66 -124 126 100 66 36 66 4 66 4 66 4 126 4 66 40 0 16
4 0 4 0 4 0 4 32 -1 -16 4 32 4 32 4 32 4 32 4 32 8 32 8 32 16 34 16 34 32 30 -64 0
0 -128 64 -128 48 -128 17 8 1 -4 2 8 8 80 16 64 32 64 -32 64 32 -96 32 -96 33 16 34 8 36 14 40 4
4 0 3 0 1 0 0 4 -1 -2 4 0 4 16 7 -8 4 16 4 16 4 16 8 16 8 16 16 16 32 -96 64 64
16 64 20 72 62 -4 73 32 5 16 1 0 63 -8 1 0 -1 -2 0 64 0 80 63 -8 8 64 4 64 1 64 0 -128
0 16 63 -8 1 0 1 0 1 0 1 4 -1 -2 1 0 1 0 1 0 1 0 1 0 1 0 1 0 5 0 2 0
2 0 2 0 7 -16 8 32 24 64 37 -128 2 -128 12 -128 113 -4 2 8 12 16 18 32 33 -64 1 0 14 0 112 0
1 0 1 0 1 0 9 32 9 16 17 12 17 4 33 16 65 16 1 32 1 64 0 -128 1 0 2 0 12 0 112 0
0 0 0 0 7 -16 24 24 48 12 56 12 0 56 0 -32 0 -64 0 -128 0 0 0 0 1 -128 3 -64 1 -128 0 0

思路:主要看懂题目,共10行,每行32个十进制数字,一行代表一个汉字,就是先要把这些十进制转化为二进制,若为负数则转换为补码(负数的二进制就是负数的补码),输入直接复制即可,运行结果为“九的九次方等于多少?”最后再根据要求求出整数答案。

推荐博客:bitset用法小结 - 自为风月马前卒 - 博客园

#include
#include
using namespace std;
int main() {
    int n, m;
    while (cin >> n >> m) {
        bitset<8> t;//t为二进制8位    biset t
        t = n;//将n赋给t,即将n转化为8位二进制 
        cout << t;//输出n的8位二进制 
        t = m;//将m赋给t,即将n转化为8位二进制 
        cout << t << endl;//输出n的8位二进制 
    }
    return 0;
}

这个就是主代码了;可以看一下运行结果:

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第15张图片 这样并不能看的很清楚,我们再稍微改进一下

代码:

#include
#include
#include
using namespace std;
int main()
{
	int n, m;
	int len;
	string temp;
	while (cin >> n >> m)
	{
		bitset<8> t;
		t = n;
		temp = t.to_string();
		 len = temp.size();
		for (int i = 0; i < len; i++)
		{
			if (temp[i] == '0')
			{
				cout << " ";
			}
			else {
				cout << "*";
			}
		}
		t = m;
		temp = t.to_string();
		 len = temp.size();
		for (int i = 0; i < len; i++)
		{
			if (temp[i] == '0')
			{
				cout << " ";
			 }
			else {
				cout << "*";
			}
		}
		cout << endl;
	}
	return 0;
}

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第16张图片

答案:387420489

乘积尾零

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第17张图片

思路:这个题不能直接乘,我们要想办法转化,

两个数相乘

2*5=10, 2*1*5*1=10,          有一个2,一个5;

4*25=100,2*2*5*5=10        有两个2,二个5;

8*125,2*2*2*5*5*5=1000   有三个2,三个5;

求尾零的个数就是求2与5的对数(即两者中最小数为两者的对数)

代码:

#include
#include
using namespace std;
int main()
{
	int num[10 * 10] = { 5650, 4542, 3554, 473, 946, 4114, 3871, 9073, 90, 4329,
		2758, 7949, 6113, 5659, 5245, 7432, 3051, 4434, 6704, 3594,
		9937, 1173, 6866, 3397, 4759, 7557, 3070, 2287, 1453, 9899,
		1486, 5722, 3135, 1170, 4014, 5510, 5120, 729, 2880, 9019,
		2049, 698, 4582, 4346, 4427, 646, 9742, 7340, 1230, 7683,
		5693, 7015, 6887, 7381, 4172, 4341, 2909, 2027, 7355, 5649,
		6701, 6645, 1671, 5978, 2704, 9926, 295, 3125, 3878, 6785,
		2066, 4247, 4800, 1578, 6652, 4616, 1113, 6205, 3264, 2915,
		3966, 5291, 2904, 1285, 2193, 1428, 2265, 8730, 9436, 7074,
		689, 5510, 8243, 6114, 337, 4096, 8199, 7313, 3685, 211 };
	int count_2 = 0, count_5 = 0;
	for (int i = 0; i < sizeof(num) / sizeof(int); i++)
	{
		int temp = num[i];
		while (temp % 2 == 0)
		{
			count_2++;
			temp /= 2;
		}
		while (temp % 5 == 0)
		{
			count_5++;
			temp /= 5;
		}
	}
	cout << min(count_2, count_5) << endl;
	return 0;
}

答案:31 

测试次数

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第18张图片

思路:

这里有两种解法 动态规划 和 手算 后一种方法比较好理解就不做解释 主要来解决一下动态规划

首先要理解一下dp[i][j] i表示手机数 j表示楼层数 dp[][]就表示有i部手机j层楼的情况下 最坏运气下需要测试的次数

我们先假设不采取最佳策略 即没一个j层的楼房 我们都要摔j次 但是当手机只有一部的情况时 这其实就是最佳策略,那么我们就可以逐渐往上拓展

假设我们已经把 i-1部手机对于所有楼层的次数已经找出,现在我们来求有i部手机时的测试次数

为此我们需要遍历 当前之前的楼层k(1~j-1)假设在k层摔坏 我们就选取i-1部手机对于k-1层楼房的最坏情况dp[i-1][k-1]+1

假如在k层没有摔坏 那么我们就可以选取i部手机对于剩下j-k层的最坏情况 dp[i][j-k]+1

由于是最坏情况 我们需要在两者之间取最大值,但我们又是采取的最佳策略 所以对于之前的非最佳策略 我们需要取最小值,即:

dp[i][j]=min(dp[i][j],max(dp[i-1][k-1],dp[i][j-k])+1);

代码

#include
using namespace std;
int dp[5][1007];
int main()
{
        ios::sync_with_stdio(false);
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 1000; j++)
                dp[i][j] = j;

        for (int i = 1; i <= 1000; i++)
            for (int j = 2; j <= 3; j++) {
                for (int k = 1; k < i; k++)
                    dp[j][i] = min(dp[j][i], max(dp[j - 1][k - 1], dp[j][i - k]) + 1);
            }
        cout << dp[3][1000] << endl;
        return 0;
}

答案:19 

快速排序

以下代码可以从数组a[]中找出第k小的元素。

它使用了类似快速排序中的分治算法,期望时间复杂度是O(N)的。

请仔细阅读分析源码,填写划线部分缺失的内容。

#include 

int quick_select(int a[], int l, int r, int k) {
	int p = rand() % (r - l + 1) + l;
	int x = a[p];
	{int t = a[p]; a[p] = a[r]; a[r] = t;}
	int i = l, j = r;
	while(i < j) {
		while(i < j && a[i] < x) i++;
		if(i < j) {
			a[j] = a[i];
			j--;
		}
		while(i < j && a[j] > x) j--;
		if(i < j) {
			a[i] = a[j];
			i++;
		}
	}
	a[i] = x;
	p = i;
	if(i - l + 1 == k) return a[i];
	if(i - l + 1 < k) return quick_select( _____________________________ ); //填空
	else return quick_select(a, l, i - 1, k);
}
	
int main()
{
	int a[] = {1, 4, 2, 8, 5, 7, 23, 58, 16, 27, 55, 13, 26, 24, 12};
	printf("%d\n", quick_select(a, 0, 14, 5));
	return 0;
}

思路:代码的大概意思就是先随机生成一个数,把比这个小的都放在它的左边,比它大的数都放在右边,这个数若是是第k小的就返回,若是小于k就再向右半部分,此时就不是第k小的了,不然就向左边去找第k小的数.

答案:(a,i+1,r,k-(i-l+1)); 

递增三元组

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第19张图片

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第20张图片 

思路:对A C数组排序后,分别二分A,C数组,这样我们就会得到A中小于B[ j ]的数和C中大于B[ j ]的数,由于 A C 是有序的,那么A数组二分数之前的数和C数组二分数之后的数也满足,两数组满足数相乘即可,这样我们边找到了包含B[ j ]的所有递增三元组的数量,遍历数组B即可。这种方法的时间复杂度为O ( n ( l o g n ) ) .

#include
#include
using namespace std;

//4
//1 3 4 5 
//1 2 2 2
//2 3 3 4

int a[100010];
int b[100010];
int c[100010];
int n;
long long ans = 0;

int main(){
    //输入数据 
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    for(int i=1;i<=n;i++){
        cin>>b[i];
    }
    for(int i=1;i<=n;i++){
        cin>>c[i];
    }
    //排序 
    sort(a+1,a+n+1);
    sort(b+1,b+n+1);
    sort(c+1,c+n+1);
    
    //定义两个指针(下标) 
    int j = 1;
    int k = 1;
    //以b为中间值 在a数组 c数组中查找 
    for(int i=1;i<=n;i++){
		while(j<=n && a[j] < b[i]) j++; //在a数组中查找第一个大于等于b[i]的数 
		while(k<=n && c[k] <= b[i]) k++; //在c数组中查找第一个大于b[i]的数 
		ans += (long long)(j-1) * (n-k+1); //计算公式 可以自己举例推导出来 
    }
    cout<

螺旋折线 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第21张图片

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第22张图片 

思路:我们可以将其看成有边长为2、4、6、8......的正方形组成的,所以可以根据给出的X、Y值求max(X,Y)来判断这个点是属于哪个正方形里面的,再从X,Y的位置判断是位于正方形的上下左右那一条边的来求dis(X,Y)

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第23张图片

代码

#include
#include
#include
#include
#include 
using namespace std;

typedef long long LL;
const int Max_n=100005;
	
int f(int x,int y,int n){
	if(x==-n){
		if(y==-n) 
			return 8*n;//n*2*4;
		return y+n;//1+(y+n-1);
	}
	if(y==n){
		return 3*n+x;//1+2*n-1+x+n;
	}
	if(x==n){
		return 5*n-y;//1+2*n-1+2*n+n-y;
	}
	if(y==-n){
		return 7*n-x;//1+2*n-1+2*n+2*n+n-x;
	}
}

int main(){
	int x,y;
	scanf("%d%d",&x,&y);
	int n=max(abs(x),abs(y));
	LL ans=1LL*n*(n-1)*4+f(x,y,n);
	printf("%lld\n",ans);
	return 0;
}

 日志统计

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第24张图片

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第25张图片 

思路:这个在代码里标记得很清楚 

代码

#include 
#include 
#include 
#include 
#include 
using namespace std;

int N,D,K,ans;

//存储日志 
struct log{
    int id,time;
};
//对id进行升序排序 
bool cmp(log a,log b)
{
    return a.time < b.time;
}


int main()
{
    //快读配置 
    std::ios::sync_with_stdio(0);
    //读取规模 
    cin>>N>>D>>K;
    
    //存储多个日志并排序 
    vector logs(N);
    for(int i = 0;i>logs[i].time>>logs[i].id;    
    }
    sort(logs.begin(),logs.end(),cmp);
    
    
    //记录答案 
    set ans;
    //记录id出现的次数
    mapcnt;
     
    int j = 0;//哨兵 
    for(int i = 0;i=K)ans.insert(logs[j].id);
            j++; 
        }
        cnt[logs[i].id]--;
    }
    
    
    for(set::iterator i = ans.begin();i !=ans.end();i++)cout<<*i<

全球变暖 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第26张图片

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第27张图片 

思路:可以这样求解,通过广度优先遍历BFS查找地图,查找过程中记录某连通陆地中临近水的陆地数量和连通块里的陆地数量,如果二者相同那么该连通陆地会被淹没

 #include 
#include
#include
#include
#include

using namespace std;

int N,ans;

char F_area[1000][1000];
int  M_area		[1000][1000];

//坐标的四周 
int Lx[] = {0,0,1,-1};
int Ly[] = {1,-1,0,0};

//存储坐标 
struct Point{
	int x,y;
};

void BFS(int i,int j)
{
	M_area[i][j] = 1;//标记该点已读 
	queue q;
	q.push({i,j});//将当前坐标存入队列 
	int cn1 = 0,cn2 = 0;//记录当前连通陆地的数量以及和水相邻的数量 
	while(!q.empty())
	{
		Point first  = q.front();
		q.pop();
		cn1 ++;//数量 
		bool swed = false;//标记该坐标四周是否有水 
		for(int k = 0;k<4;++k)//查找四周 
		{
			int x = first.x + Lx[k];
			int y = first.y + Ly[k];
			if(0<=x&&x>N;
	
	//读取地图 
	for(int i = 0;i>F_area[i][j];
		}
	}
	//进行广搜查找 
	for(int i = 0;i

乘积最大 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第28张图片

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第29张图片

思路:家人们肝不动了,拿大佬的代码,在这里给大家参考吧,共同学习

博客:蓝桥杯-历届试题-乘积最大_柯基吹泡泡的博客-CSDN博客_乘积最大蓝桥杯

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第30张图片

代码

#include
#include
using namespace std;
const int N=1e5+10;
long long int st[N];
int main()
{
    int n,k;
    cin>>n>>k;
    int ft=0;
    for(int i=0;i>st[i];
        if(st[i]<0)ft++;
    }
    sort(st,st+n);
    long long int ans=1;
    if(k%2!=0&&ft==n)
    {
        for(int i=0;i=st[v]*st[v-1])
        {
            long long pp=st[u]*st[u+1]%1000000009;
            ans=ans*pp%1000000009;
            ans=ans%1000000009;
            u+=2;
            tt+=2;
        }
        else
        {
            long long oo=st[v]*st[v-1]%1000000009;
            ans=ans*oo%1000000009;
            ans=ans%1000000009;
            v=v-2;
            tt=tt+2;
        }
    }
    cout<

           好啦,今天就到这里,学累了吧xdm,上图缓解视觉疲劳

 

蓝桥杯——2018第九届C/C++真题[省赛][B组]_第31张图片

你可能感兴趣的:(#,C/C++蓝桥杯真题,c++,算法,蓝桥杯,c语言,数据结构)