2019儿童节前一天考试感想

/*
俗话说,要有前言
说起今天的考试,不免有些惭愧
普及组试题,充足的时间,“试友”一半是学弟学妹
而我,虽然可能可以用起步晚来安慰自己(现在是不存在的了),但是这么多人中垫底,rating掉93,是不像话的。
接下来有请题目粗略分析(赶时间)很考试感想出台……
*/
首先,再7点多的时候老刘把题目发下来,断了网,我们拔掉耳机,桌面只留打开的Word和Dev-c++,营造出一个良好的做题环境。
我很听老师的话,准备把每道题都看一遍。
第一题,题目很短,第一反应便是暴力枚举,脑子里留下了念想,但又不敢保证;放着
第二题 添加了一些故事性的内容,整体看来有点像小学数学题,瞧过样例后,自认为样例很良心,看过每一组数据分别是a,b,c三个数,直觉告诉我输出是a+b-c(很直观),仔细看发现真的是这样,兴奋的我生怕待会儿会忘记,就先打破了规矩,先把这题打了,十行不到,样例都过了。接下去看
第三题 题目也很短,也有故事性内容,比如“古天乐”,看样子也是似曾相识的小学数学题,但我不敢轻举妄动,余光瞟到旁边的那位已经开始画这题的图了(有点虚)。继续
第四题 像这种格子跳啊跳的第一反应就是搜索,但我不擅长这茬,就算是模板,也不敢轻举妄动,留着
第五题因为记忆中习惯于四道题,第一次没有往下看,题目做了一半之后才意外发现,第一反应觉得是数学题,全排列之类的,有点想法又不会操作。嗯就是这样。

(以下题目不知是否改编,纯属OJ原题目)

T1 Classroom Watch

题目大意:
给出一个正整数 n,现在问存在多少个 x,使得 x在十进制下的每一位之和加上 x 等于 n。
在这里插入图片描述
老刘说,因为考虑到大众感受,这是原本没有,新加的题(疯狂暗示很水,为下文我的小题大做做铺垫,形成强烈对比,突出我很二的个性……)
数据范围貌似挺大,刚刚的暴力想法瞬间蒸发。然后我开始立马低头推数学方法,用了一整张草稿纸。推导过程中我发现不管是n还是x,各个位数之和是<81的,但沉醉于推到兴头的我没有意识到完全可以从n-100~n的范围内枚举x,只要符合条件就可以,因此我走向了不归之路。推出来后,自认为非常不错,还在Dev里备注了思路,如图(对于我这种数学渣子来说,心中很有成就感)在这里插入图片描述
花了大把时间的苦工,结果只有30分,我表示不再相信自信心……最后我就是老师所说的“简单题目复杂化”之人……在这里插入图片描述
然而正解就不必多说了:

#include<bits/stdc++.h>
using namespace std;
int n;
int ans[5555];
int main()
{
	freopen("num.in","r",stdin);
	freopen("num.out","w",stdout);
	scanf("%d",&n);
	int cnt=0;
    for(int i=max(1,n-1000);i<=n;i++)
    {
    	int j=i,sum=0;
    	while(j>0)
    	{
    		sum+=j%10;
    		j/=10;
		}
		if(sum+i==n) ans[++cnt]=i;
	}
 	printf("%d\n",cnt);
 	for(int i=1;i<=cnt;i++)
//	cout<<ans[i]<<endl; 
	printf("%d\n",ans[i]);
	return 0;
}

T2 组合技能combo

题目大意:
给定A、B、C三个数,使得A-a=B-b=C-a-b。求出A-a(即B-b,C-a-b)利润,数据保证为正数。

老刘说他答应给我们考一次A+B,然后这题就出现了(良心!/竖起了大拇指)
这个相信那些数学大佬都不用动脑子,从样例里也能恰好看出一定规律,这说明考试中的直觉也是比较重要的。那么不必多说,直接将做法(因为能够自己一遍A,说话也比较有底气)
思路:
设A-a=B-b=C-a-b=x
则需解x
A=x+a,B=x+b,C=x+a+b
x=A+B-C=x+x+a+b-(x+a+b)=x
Perfect
代码(超简短):

#include<bits/stdc++.h>
using namespace std;
int main()
{
	freopen("combo.in","r",stdin);
	freopen("combo.out","w",stdout);
	int t;
	cin>>t;
	for(int i=1;i<=t;i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		cout<<a+b-c<<endl;
	}
	return 0;
}

T3 表面积

题目大意:
积木图可以抽象为一个n*m的网格图,其中第(i,j)的位置有A[i][j]个积木。求表面积。

在这里插入图片描述
看了如此有内涵的图顿时有点懵,但是又是求表面积,联想到小学数学题也就安心了。表面积就是内看到的面积,即没有并在一起的面积,没被遮住就没有被并在一起,比周围的某一个高的地方就没有被遮住。因为除了读入数据,其他坐标的高度默认为0,而且题目非常良心地说“1<=a[i][j]<=100”。除了俯视,即上表面,和下表面一定都是n*m外,就只要求侧面积即可。那么枚举每一个坐标高度,累加比四周坐标高出的部分即可。
代码如下:

#include<bits/stdc++.h>
using namespace std;
int n,m;
long long ans;
int a[200][200];
int main()
{
	freopen("surface.in","r",stdin);
	freopen("surface.out","w",stdout);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	 scanf("%d",&a[i][j]);
	for(int i=1;i<=n;i++)
	 for(int j=1;j<=m;j++)
	  {
	  	int fr=max(0,a[i][j]-a[i-1][j]);
	  	int beh=max(0,a[i][j]-a[i+1][j]);
	  	int l=max(0,a[i][j]-a[i][j-1]);
	  	int r=max(0,a[i][j]-a[i][j+1]);
	  	ans=ans+(long long)(fr+beh+l+r);
	  }
	printf("%lld\n",ans+2*n*m);
	return 0;
}

和意外的是我的这一题爆0了,原因是文件名打错,少写了一个"r"在这里插入图片描述

T4 红皇后的旅行

题目大意:
给定一个n*n的棋盘,行和列标号为0,1,2,….,n-1。在棋盘的(i_start,j_start)位置上有一位红皇后,每次红皇后可以往六个方向走,如图所示:
现在红皇后想去(i_end,j_end)点,求最短距离,并且输出一条路径。
显然最短路径有无穷条,请按照以下顺序来搜索:UL, UR, R, LR, LL, L。
如果无解,输出Impossible

在这里插入图片描述
Sample Input
7
6 6 0 1
Sample Output
4
UL UL UL L
Sample Explain
在这里插入图片描述
这近乎于SPFA模板题,只要加一些优化即可,而我并没有做出来,输出“Impossible”会有36分/xk
很奇怪,对于搜索,我不管复习几遍都好像没有很大的把我能写出来,我认为,搜索的那些模板和最短路的好像好像,虽然我之前相以有趣的方式加强对最短路的印象与理解写了一篇“近来算法想象篇”,结果并没什么卵用。
代码应该无需过多解释了:

#include<bits/stdc++.h>
using namespace std;
int n;
int sx,sy,ex,ey;
int vis[500][500],dis[500][500];
string towards[10]={"UL","UR","R","LR","LL","L"};
int dx[6]={-2,-2,0,2,2,0};
int dy[6]={-1,1,2,1,-1,-2};
struct loc
{
	int x,y;
}from[500][500];//from[i][j]记录从哪个坐标走到(i,j) 
queue<loc> q;
void go()//SPFA
{
	for(int i=0;i<=n+100;i++)
	 for(int j=0;j<=n+100;j++)
	  dis[i][j]=500000000;
	dis[sx][sy]=0;
	vis[sx][sy]=0;
	loc a;
    a.x=sx,a.y=sy;
	q.push(a);
	while(!q.empty())
	{
		a=q.front();
		q.pop();
		vis[a.x][a.y]=0;
		for(int i=0;i<6;i++)
		{
			loc aa;
			aa.x=a.x+dx[i];
			aa.y=a.y+dy[i];
			if(aa.x<0||aa.x>=n||aa.y<0||aa.y>=n)
			continue;
			if(dis[a.x][a.y]+1<dis[aa.x][aa.y])
			{
				dis[aa.x][aa.y]=dis[a.x][a.y]+1;
				from[aa.x][aa.y].x=a.x;
				from[aa.x][aa.y].y=a.y;
				if(!vis[aa.x][aa.y])
				{
					vis[aa.x][aa.y]=1;
					q.push(aa);
				}
			}
		}
	}
}
void get_way(int frx,int fry,int tox,int toy)
{
	if(frx==0&&fry==0)return;
	get_way(from[frx][fry].x,from[frx][fry].y,frx,fry);
    for(int i=0;i<6;i++)
    if(frx+dx[i]==tox&&fry+dy[i]==toy)
    {
    	cout<<towards[i]<<' ';
    	break;
	}
	return;
}
int main()
{
	freopen("redqueen.in","r",stdin);
	freopen("redqueen.out","w",stdout);
	scanf("%d",&n);
	scanf("%d%d%d%d",&sx,&sy,&ex,&ey);
	go();
	if(dis[ex][ey]==500000000)
	printf("Impossible\n");
	else
	{
	  printf("%d\n",dis[ex][ey]);
	  get_way(ex,ey,0,0);
	}
	return 0;
}

T5 构造序列

题目大意:
有一个长度为n的序列A,其中A[1]=1,A[n]=x,A[2…n-1]可以是1至k间任意一个正整数。求有多少个不同的序列,使得相邻两个数不同。
答案对10^9+7取模。
在这里插入图片描述
上文说了,这道题实在之后看到的,而且觉得它像排列组合,但实际上并不是,因此我也没写出来。
很显然,题目规定第一个数固定为1,那么不考虑后面对当前的影响,共有K个数,相邻的数不能相同,因此每次*(k-1);但是其中第n-1个位置会包括与n位置上(n位置上固定为数x)的数相同的情况,这不符合题意所以在上面的操作之后要减去以n-1这个位置为x的时候的方案数
详情看代码注释:

#include<bits/stdc++.h>
using namespace std;
int n,k,x;
long long o_f[255555];//only_first 
//题中固定第一个为1,不考虑最后一个的影响的到第i个数的方案数 
long long now_x[255555];
//第一个数固定为1,如果当前数是x(即固定的一个数)时,到当前数的方案数 
long long const mod=1000000007;
int main()
{
	freopen("construct.in","r",stdin);
	freopen("construct.out","w",stdout);
	cin>>n>>k>>x;
	o_f[2]=k-1;
	for(int i=3;i<n;i++)
	o_f[i]=o_f[i-1]*(k-1)%mod;//共有K个数,相邻的数不能相同,因此*(k-1)
    if(x==1)
	  now_x[2]=0;//表示第而个数的位置是固定的x,且x=1,但题目固定第一个数为1,又不能相邻的相同,因此没有方案
    else
	  now_x[2]=1;
	for(int i=3;i<=n;i++)
	 now_x[i]=(o_f[i-1]-now_x[i-1]+mod)%mod; //以当前数为x时,前一个数不考虑x影响的方案数减去以前一个数为x的方案数(因为前一个数为x,当前数又为x不符合要求) 
	cout<<now_x[n]<<endl;
	return 0;
}

感谢老师和大佬有请讲解,帮同学们过了这一题!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值