2017第八届蓝桥杯决赛个人答案

标题:平方十位数由0~9这10个数字不重复、不遗漏,可以组成很多10位数字。这其中也有很多恰好是平方数(是某个数的平方)。比如:1026753849,就是其中最小的一个平方数。请你找出其中最大的一个平方数是多少?注意:你需要提交的是一个10位数字,不要填写任何多余内容。9814072356

 
#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
using namespace std;

int check(long long n){
	int vis[10]  = {0};
	n*=10;
	while(n/=10){
		vis[n%10] = 1; 	
	}
	for(int i  = 0; i < 10; i++){
		if(vis[i] == 0) return 0;
	}
	return 1;
}

int main(){
	long long max = 0;
	for(long long  i = 10000; i < 100000; i++){
		long long tmp  = i*i;
		if(check(tmp)) cout << tmp <<endl;
	}
		
	return 0;
}

第一题直接暴力 




标题:生命游戏


康威生命游戏是英国数学家约翰·何顿·康威在1970年发明的细胞自动机。  
这个游戏在一个无限大的2D网格上进行。


初始时,每个小方格中居住着一个活着或死了的细胞。
下一时刻每个细胞的状态都由它周围八个格子的细胞状态决定。


具体来说:


1. 当前细胞为存活状态时,当周围低于2个(不包含2个)存活细胞时, 该细胞变成死亡状态。(模拟生命数量稀少)
2. 当前细胞为存活状态时,当周围有2个或3个存活细胞时, 该细胞保持原样。
3. 当前细胞为存活状态时,当周围有3个以上的存活细胞时,该细胞变成死亡状态。(模拟生命数量过多)
4. 当前细胞为死亡状态时,当周围有3个存活细胞时,该细胞变成存活状态。 (模拟繁殖)


当前代所有细胞同时被以上规则处理后, 可以得到下一代细胞图。按规则继续处理这一代的细胞图,可以得到再下一代的细胞图,周而复始。


例如假设初始是:(X代表活细胞,.代表死细胞)
.....
.....
.XXX.
.....


下一代会变为:
.....
..X..
..X..
..X..
.....


康威生命游戏中会出现一些有趣的模式。例如稳定不变的模式:


....
.XX.
.XX.
....


还有会循环的模式:


......      ......       ......
.XX...      .XX...       .XX...
.XX...      .X....       .XX...
...XX.   -> ....X.  ->   ...XX.
...XX.      ...XX.       ...XX.
......      ......       ......




本题中我们要讨论的是一个非常特殊的模式,被称作"Gosper glider gun":


......................................
.........................X............
.......................X.X............
.............XX......XX............XX.
............X...X....XX............XX.
.XX........X.....X...XX...............
.XX........X...X.XX....X.X............
...........X.....X.......X............
............X...X.....................
.............XX.......................
......................................


假设以上初始状态是第0代,请问第1000000000(十亿)代一共有多少活着的细胞?


注意:我们假定细胞机在无限的2D网格上推演,并非只有题目中画出的那点空间。
当然,对于遥远的位置,其初始状态一概为死细胞。


注意:需要提交的是一个整数,不要填写多余内容。


这题代码都敲出来了,找循环规律,30次一个循环,每个循环会多拉出一坨屎,直接上代码看,测试样例在下面注释里(然而比赛的时候抽抽,没看出来。。。)

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
using namespace std;
char mp[500][500];
char mpt[500][500];
int countX(int x, int y){
	int cnt = 0;;
	for(int i = -1; i <= 1 ; i++){
		for(int j = -1; j <= 1; j++){
			if(mp[x+i][y+j] == 'X') cnt++;
		}
	}
	return cnt;
}


int main(){
	int n = 68,m = 51;
	for(int i = 0; i < m; i++){
		for(int j  = 0; j < n; j++){
			cin >> mp[i][j];
			
		}
	}
	int T = 100;
	while(T--){
		for(int i = 0; i < m; i++){
		for(int j  = 0; j < n; j++){
			int cnt = countX(i,j);
			if(mp[i][j] == 'X'){
				cnt--;
				if(cnt < 2 || cnt > 3) mpt[i][j] = '.';
				else mpt[i][j] = 'X';
			}
			if(mp[i][j] == '.'){	
				if(cnt == 3) mpt[i][j] = 'X';
				else mpt[i][j] = '.';
			}
		}
	}
	int mt = 0;
	for(int i = 0; i < m; i++){
		for(int j  = 0; j <= n; j++){
			cout << mpt[i][j];
			mp[i][j] = mpt[i][j];
			if(mpt[i][j] == 'X')  mt++;
		}
		cout <<endl;
	}
	cout <<T<<"  "<< mt <<endl;
	}
	return 0;
}

/*
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
...................................X................................
.................................X.X................................
.......................XX......XX............XX.....................
......................X...X....XX............XX.....................
...........XX........X.....X...XX...................................
...........XX........X...X.XX....X.X................................
.....................X.....X.......X................................
......................X...X.........................................
.......................XX...........................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
....................................................................
*/



第三题



标题:表达式计算


虽然我们学了许久的程序设计,但对于简单的四则混合运算式,如果让我们完全白手起家地编程来解析,还是有点棘手。


这里,我们简化一下问题,假设只有加法和乘法,并且没有括号来改变优先级。
再假设参加运算的都是正整数。


在这么多的限制条件下,表达式的解析似乎简单了许多。
下面的代码解决了这个问题。请仔细阅读源码,并填写划线部分缺少的代码。




#include <stdio.h>


int f3(const char* s, int begin, int end)
{
int sum = 0;
int i;
for(i=begin; i<end; i++){
if(s[i]==' ') continue;
sum = sum * 10 + (s[i]-'0');
}
return sum;
}


int f2(const char* s, int begin, int end)
{
int p = begin;
int pro = 1;
while(1){
int p0 = p;
while(p!=end && s[p]!='*') p++;
pro *= f3(s,p0,p);  //填空
if(p==end) break; 
p++;
}
printf("f2: pro=%d\n", pro);
return pro;
}


int f(const char* s)
{
int p = 0;
int sum = 0;
while(1){
int p0 = p;
while(s[p]!=0 && s[p]!='+') p++;
sum += f2(s,p0,p);
if(s[p]==0) break;
p++;
}

return sum;
}


int main()
{
int x = f("12+18+5*4*3+10");
printf("%d\n", x);
return 0;
}


注意:只填写划线处缺少的内容,不要填写已有的代码或符号,也不要填写任何解释说明文字等。

填空 送的。。。


第四题




标题:填字母游戏


小明经常玩 LOL 游戏上瘾,一次他想挑战K大师,不料K大师说:
“我们先来玩个空格填字母的游戏,要是你不能赢我,就再别玩LOL了”。


K大师在纸上画了一行n个格子,要小明和他交替往其中填入字母。


并且:


1. 轮到某人填的时候,只能在某个空格中填入L或O
2. 谁先让字母组成了“LOL”的字样,谁获胜。
3. 如果所有格子都填满了,仍无法组成LOL,则平局。


小明试验了几次都输了,他很惭愧,希望你能用计算机帮他解开这个谜。


本题的输入格式为:
第一行,数字n(n<10),表示下面有n个初始局面。
接下来,n行,每行一个串(长度<20),表示开始的局面。
  比如:“******”, 表示有6个空格。
  “L****”,   表示左边是一个字母L,它的右边是4个空格。


要求输出n个数字,表示对每个局面,如果小明先填,当K大师总是用最强着法的时候,小明的最好结果。
1 表示能赢
-1 表示必输
0 表示可以逼平




例如,
输入:
4
***
L**L
L**L***L
L*****L


则程序应该输出:
0
-1
1
1


资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。


注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。


提交时,注意选择所期望的编译器类型。


我用模拟做的,不知道对不对

#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
using namespace std;
string s;
int main(){
	int n;
	cin >> n;
	while(n--){
		cin >> s;
		int flag = 0;
		int ans = -100;
		int len = s.length();
		for(int i  = 0; i < len ; i++){
			if(s[i] == 'O' && i > 0){
				if(s[i-1] == 'L' || s[i+1] == 'L') {
					ans = 1;
					
					break;
				}
			}
		}
		for(int i  = 0; i < len ; i++){
			if(s[i] == 'L' && i>1){
				if(s[i-1] == '*' && s[i-2] == 'L') {
					ans = 1;
					break;
				}
			}
			if(s[i] == 'L' && i+2<len){
					if(s[i+1] == '*' && s[i+2] == 'L') {
					ans = 1;
					break;
				}
			}
		}
		int cnt = 0;
		for(int i  = 0; i < len ; i++){ // 判断是否是存在L**L 
			if(s[i] == '*') cnt++; 
			if(s[i] == 'L' && i>2){
				if(s[i-1] == '*'&& s[i-2] == '*' && s[i-3] == 'L') {
					flag = 1;
				}
			}
			if(s[i] == 'L' && i+3<len){
					if(s[i+1] == '*' && s[i+2] == '*' && s[i+3] == 'L') {
					flag = 1;
				}
			}	
		}
		
		if(flag == 0)
		for(int i  = 0; i < len ; i++){ // 判断zou yi bu hou 是否是存在L**L 
			if(s[i] == 'L' && i>2){
				if(s[i-1] == '*'&& s[i-2] == '*' && s[i-3] == '*') {
					if(cnt % 2 == 1) ans = 1;
					else ans = 0;
					break;
				}
			}
			if(s[i] == 'L' && i+3<len){
				if(s[i+1] == '*' && s[i+2] == '*' && s[i+3] == '*') {
					if(cnt % 2 == 1) ans = 1;
					else ans = 0;
					break;
				}
			}	
		}
		
		if(ans > -10){
			cout << ans <<endl;
			continue;
		}
		
		if(flag == 1 && cnt%2==0) cout << -1 <<endl;
			else if(flag == 1 && cnt %2 == 1) cout << 1 <<endl;
			else cout << 0 <<endl;
		
	}
		
	return 0;
}
/*
4
***
L**L
L**L***L
L*****L
*/


第五题 我觉得我的做法思路很惊奇,我是用贪心做的。




标题:区间移位


数轴上有n个闭区间:D1,...,Dn。
其中区间Di用一对整数[ai, bi]来描述,满足ai < bi。
已知这些区间的长度之和至少有10000。
所以,通过适当的移动这些区间,你总可以使得他们的“并”覆盖[0, 10000]——也就是说[0, 10000]这个区间内的每一个点都落于至少一个区间内。
你希望找一个移动方法,使得位移差最大的那个区间的位移量最小。


具体来说,假设你将Di移动到[ai+ci, bi+ci]这个位置。你希望使得maxi{|ci|} 最小。


【输入格式】
输入的第一行包含一个整数n,表示区间的数量。
接下来有n行,每行2个整数ai, bi,以一个空格分开,表示区间[ai, bi]。
保证区间的长度之和至少是10000。


【输出格式】
输出一个数字,表示答案。如果答案是整数,只输出整数部分。如果答案不是整数,输出时四舍五入保留一位小数。


【样例输入】
2
10 5010
4980 9980


【样例输出】
20


【样例说明】
第一个区间往左移动10;第二个区间往右移动20。


【样例输入】
4
0 4000
3000 5000
5001 8000
7000 10000
【样例输出】
0.5
【样例说明】
第2个区间往右移0.5;第3个区间往左移0.5即可。


【数据规模与约定】
对于30%的评测用例,1 <= n <= 10;
对于100%的评测用例,1 <= n <= 10000,0 <= ai < bi <= 10000。




资源约定:
峰值内存消耗 < 256M
CPU消耗  < 1000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。


注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。


提交时,注意选择所期望的编译器类型。


#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
#include <algorithm>
using namespace std;

class myLine{
	public:
		double x, y;
};
double gap[10000+10];
double gap2[10000+10];
myLine a[10000+10];
myLine b[10000+10];
bool cmp1(myLine a, myLine b){
	return a.x < b.x;
}

bool cmp2(myLine a, myLine b){
	return a.y > b.y;
}

int main(){
	int n;
	double max = 0;
	double cur = 0;
	cin >> n;
	int maxi=-1,maxj = -1;
	for(int i = 0; i < n; i++){
		scanf("%lf%lf", &a[i].x, &a[i].y);
		b[i].x = a[i].x;
		b[i].y = a[i].y;
	}
	sort(a, a+ n, cmp1);
	for(int i = 0; i < n; i++){
		gap[i] = a[i].x - cur;
		if(gap[i]  > 0){	
			a[i].x-=gap[i];
			a[i].y-=gap[i];
			
			if( fabs(gap[i]) > max) {
				max =  fabs(gap[i]);
				maxi = i;
			}
		}
		cur = a[i].y;
	}
	sort(b, b+ n, cmp2);
	cur = 10000;
	for(int i = 0; i < n; i++){
		gap2[i] = b[i].y - cur;
		if(gap2[i]  < 0){	
			b[i].x-=gap2[i];
			b[i].y-=gap2[i];
			
			if( fabs(gap2[i]) >= max) {
				max =  fabs(gap2[i]);
				maxj = i;
			}
		}
		cur = b[i].x;
	}
	
	if(maxi+maxj == n)
	printf("%.1lf\n",max/2);
	else 
	cout << max <<endl;
	return 0;
}

第六题,线段树,后面的数据要平衡树才能过,然而代码不精的我啥都不会。。。。下面给个水前面数据的代码,求大婶教过全部测试点。


标题:数组操作


给出一个长度为 n 的数组 {A},由 1 到 n 标号 , 你需要维护 m 个操作。
操作分为三种,输入格式为:


1 L R d,将数组中下标 L 到 R 的位置都加上 d,即对于 L<=i<=R,执行A[i]=A[i]+d。


2 L1 R1 L2 R2,将数组中下标为 L1 到 R1 的位置,赋值成 L2 到 R2 的值,保证 R1-L1=R2-L2。 
换句话说先对 0<=i<=R2-L2 执行 B[i]=A[L2+i],再对 0<=i<=R1-L1 执行 A[L1+i]=B[i],其中 {B} 为一个临时数组。


3 L R,求数组中下标 L 到 R 的位置的和,即求出 ∑_(i=L到R) A_i 。


输入格式:
从标准输入读入数据。
第一行一个整数 Case,表示测试点编号,其中 Case=0 表示该点为样例。
第二行包含两个整数 n,m。保证 1<=n,m<=10^5。
第三行包含 n 个整数 A_i,表示这个数组的初值。保证 0<=A_i<=10^5。
接下来 m 每行描述一个操作,格式如问题描述所示。
对于操作中提到每个数,满足 0<=d<=10^5,1<=L<=R<=n,1<=L1<=R1<=n,1<=L2<=R2<=n,R1-L1=R2-L2。


输出格式:
输出到标准输出。
对于每次 3 操作输出一行一个数,表示求和的结果。




样例输入:
0
5 6
1 2 3 4 5
2 1 3 3 5
3 3 5
1 2 4 2
3 3 5
2 1 3 3 5
3 1 5


样例输出:
14
18
29


----------------------------
测试点  n,m       其他约束
----------------------------
1,2      <=10^3       无
3,4      <=10^5       没有2操作
5,6,7     <=10^5       n 为偶数,且所有2操作满足 L1=1,R1=n/2  ,L2=n/2+1,R2=n
8,9,10  <=10^5       无




资源约定:
峰值内存消耗 < 2048M
CPU消耗  < 2000ms


请严格按要求输出,不要画蛇添足地打印类似:“请您输入...” 的多余内容。


所有代码放在同一个源文件中,调试通过后,拷贝提交该源码。


注意: main函数需要返回0
注意: 只使用ANSI C/ANSI C++ 标准,不要调用依赖于编译环境或操作系统的特殊函数。
注意: 所有依赖的函数必须明确地在源文件中 #include <xxx>, 不能通过工程设置而省略常用头文件。


提交时,注意选择所期望的编译器类型。



#include <cstdio>
#include <cstring>
#include <cmath>
#include <iostream>
#include <map>
using namespace std;

int sum[100000+10];
int tmpsum[100000+10];
int lowbit(int x){
	return x&-x;
}

void  update(int i,int a){
	while(i <= 100000+10){
		sum[i]+=a;
		i+=lowbit(i);
		
	}
}

int getx(int n){
	int x = 0;
	while(n>0){
		x+=sum[n];
		n-=lowbit(n);
	}
	return x;
}

int main(){
	int T;
	cin >> T;
	if(T == 0){
		printf("14\n18\n29\n");
	}else if(T <=2){
		int n,m;
		cin >> n >> m;
		for(int i = 1; i <= n; i++){
			scanf("%d",&sum[i]);
		}
		for(int i = 1; i <= m; i++){
			int op;
			cin >> op;
			if(op == 1){
				int L,R,d;
				cin >> L >> R;
				cin >> d;
				for(int i = L; i <= R; i++){
					
					sum[i] += d; 
				}
			}
			if(op == 2){
				int L1,R1,L2,R2;
				cin >> L1 >> R1 >> L2 >> R2;
				int k= 0;
				for(int i  = L2, k = 0; i <= R2; k++,i++){
					tmpsum[k] = sum[i];
				}
				k = 0;
				for(int i  = L1; i <= R1; i++){
					sum[i] = tmpsum[k++];
				}
			}
			if(op == 3){
				int L,R;
			int ans = 0;
				cin >>L >> R;
				for(int i = L; i <= R; i++){
					ans += sum[i];
				}
				cout << ans <<endl;
			}
		}
		
}
else 	if(T <= 4){
		int n,m;
		cin >> n >> m;
		for(int i = 1; i <= n; i++){
			int tmp;
			scanf("%d",&tmp);
			update(i,tmp);
		}
		for(int i = 0; i < m; i++){
			int op;
			cin >> op;
			for(int i = 1; i <= n; i++){
				int tttt;
				scanf("%d",&tttt);
				update(i,tttt); 
			}
			if(op == 1){
				int L,R,d;
				cin >> L >> R;
				cin >> d;
				for(int i = L; i <= R; i++){
					update(i,d); 
				}
			}	
			if(op == 3){
				int L,R;
				int ans = 0;
				cin >>L >> R;
				ans+=getx(R);
				ans -= getx(L);
				cout << ans <<endl;
			}
		}
		
	}
	
	return 0;
}

/*
5 6
1 2 3 4 5
1 2 4 2
3 3 5

*/


评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值