2019.4.2校内编程比赛大一组专题

版权声明:那啥,咱一个萌新写的东西没啥价值。但是也要打个招呼吧…… https://blog.csdn.net/Miaplacidus/article/details/88994987

和两位大佬一起组队参加了昨天的校内的高年级组编程比赛……
虽说似乎一题也没解出来,但是过程也是蛮欢乐的……
下面这些是参加了大一组的同学的竞赛题目。
大多都能在网上找到原题

Problem A 幸运儿

现在考试的所有学生需要评选出一位幸运儿,评选标准:每个学生给出一个数字(1-100间整数),哪位学生给出的数字最接近全班学生给出所有数字的平均值的2/3,即为获胜者。请给出你的答案,并简要说明理由。

这题我一开始以为就是写代码……后来发现似乎是个脑筋急转弯?
然后又觉得是概率论与数理统计,要计算期望值
假设参赛学生一共86人,除我以外85人
E ( x ) = X 1 P 1 + X 2 P 2 + + X n P n = 1 100 + 2 100 + 3 100 + + 100 100 = 50.5 E(x)=X1P1+X2P2+……+XnPn =\frac{1}{100}+\frac{2}{100}+\frac{3}{100}+…+\frac{100}{100}=50.5

所以我选择 34 34

2019年4月3日22点28分

Problem B 有效括号

给定一个只包括**’(’ , ‘)’ , ‘{’ , ‘}’ ,’[’ , ‘]’**的字符串,判断字符串是否有效,有效字符串需满足:
(1) 左括号必须用相同类型的右括号闭合。
(2) 左括号必须以正确的顺序闭合。
Input
待判定的字符串
Output
true或false,分别表示对应的字符串是否有效
Sample Input
()
([]{})
(]

Sample Output
true
true
false

/*有效括号——数据结构——栈运用,非栈尝试解题
*思路:读入字符串后,判断奇偶,奇数直接false 
先只处理一种括号,像洋葱芯一样,从紧挨着的(不考虑另外两组)左右括号配对并消去(赋值为别的)
消去括号的循环进行strlen()/2次后,遍历,若存在此种括号剩余,则false
*/ 
#include<stdio.h>
#include<string.h>
int judge(char left,char right);
void search(char le,char ri);
char str[1005];
int main(void)
{
	while(gets(str)!=NULL){//fgets(str,1000,stdin)!=NULL,空字符转换懒得写了 
		if(strlen(str)%2!=0){
			printf("flase\n");
			continue;
		}
		if(judge('(',')')+judge('[',']')+judge('{','}')==3)
			printf("true\n"); 
		else
			printf("flase\n");
	}
	return 0;
}
int judge(char left,char right)//调用search,转换所有特定的括号,并判断是否匹配 
{
	int i;
	for(i=0;i<strlen(str)/2;i++)//我知道这么写很浪费…… 
		search(left,right);
	for(i=0;i<strlen(str)&&str[i]!=left&&str[i]!=right;i++)
		continue;
	if(i<strlen(str))
		return 0;
	else
		return 1;
}
void search(char le,char ri)//只找出一对正对着的对应括号,并修改为'0' 
{
	int i,j;
	for(i=0;i<strlen(str)&&str[i]!=le;i++)
		continue;
	for(j=i;j<strlen(str)&&str[j]!=ri;j++)
		if(str[j]==le)
			i=j;
	if(str[i]==le&&str[j]==ri)
		str[i]=str[j]='0';
	return;
}

这题我从中午敲完题目就开始想,晚饭后回寝写了能有一个多小时,我居然做出来了,没有用网上使用栈的方法,给我NB坏了,叉会腰
2019年4月3日19点19分

Problem C 导弹拦截

某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统,但是这种导弹拦截系统有一个缺陷::虽然它的第一发炮弹能够到达任意的高度,但是以后每一发炮弹都不能高于前一发的高度。某天,雷达捕捉到敌国的导弹来袭。由于该系统还在试用阶段,所以只有一套系统,因此有可能不能拦截所有的导弹。
现给你一组数据,导弹总个数(正整数),输入导弹依次飞来的高度(雷达给出的高度数据是不大于30000 的正整数)

①计算这套系统最多能拦截多少导弹?

Sample Input
8
389 207 155 300 299 170 158 65

Sample Output
6

#include<stdio.h>
#include<string.h>
int max(int a,int b);
int arr[1000]={0},d[1000];
int main(void)
{
	int n,x=0;
	while(scanf("%d",&n)!=EOF&&n!=0){
		memset(d,0,sizeof(int));
		int i,j;
		for(i=0;i<n;i++)
			scanf("%d",&arr[i]);
		d[0]=1;//第一个导弹编号为0
		for(i=1;i<n;i++){
			int maxium=0;
			for(j=0;j<i;j++){
				if(arr[j]>arr[i]){
					maxium=max(d[j],maxium);
				}
			}
			d[i]=maxium+1;
		} 
		for(i=0;i<n;i++)
			x=max(d[i],x);
		printf("%d\n",x);
	}
	return 0;
}
int max(int a,int b)
{
	return (a>b)?a:b;
}

花了14分02秒敲代码,4分15秒debug
很典型的一道求最长单调递减子序列,但我还没理解好……
2019年4月5日10点45分

扫描二维码关注公众号,回复: 6033020 查看本文章

②计算拦截所有导弹需要配备多少套这种导弹拦截系统。

Sample Input
8
389 207 155 300 299 170 158 65

Sample Output
2

#include<stdio.h>
#include<string.h>
int missile[1000],mimin[1000];//分别记录导弹高度,系统的最小高度
int main(void)
{
	int n,num=0;
	while(scanf("%d",&n)!=EOF&&n!=0){
		int i,j;
		for(i=0;i<n;i++){
			scanf("%d",&missile[i]);
		}
		memset(mimin,0,sizeof(int));
		num=1;//第一个导弹编号为0,第一个系统编号为0
		mimin[0]=missile[0];
		for(i=1;i<n;i++){//遍历每个导弹,并将这个值赋给与它最接近且大于它的系统
			int sub=32767,locate=-1,temp;//将sub定义为一个相当大的数,locate定义为负数,方便下一步进行判断
			for(j=0;j<num;j++){//每个导弹遍历一遍当前系统
				if((temp=mimin[j]-missile[i])<=sub&&temp>=0){//寻找数值最接近且不小于它的系统 
					sub=temp;
					locate=j;
				}
			}
			if(locate>=0){//将导弹高度赋给与它最接近且不小于它的系统
				mimin[locate]=missile[i];
			}
			else{//若每个系统都小于它,则启动一个新系统,拦截此导弹 
				num++;
				mimin[num-1]=missile[i];
			}
		}
		printf("%d\n",num);
	}
	return 0;
}

这个第二问肝了一中午……
之前还是被题目吓到了,其实没那麽复杂……
2019年4月5日13点00分

Problem D 圆桌分座

一个屋子里有若干张桌子和若
干个人。如果3个人一桌,多2个人;如果5个人一桌,多4个人;如果7个人一桌,多6个人;如果9个人一桌,多8个人;如果11个人一桌,正好。请问这屋里至少多少人?并给出解题思路。

#include<stdio.h>
int main(void)
{
	int n=1;
	while(n%3!=2||n%5!=4||n%7!=6||n%9!=8||n%11!=0)
		n++;
	printf("%d",n);
	return 0;
}

Output 2519
水完B题后滚去图书馆肝大物,闭馆后又回来水D题
2019年4月3日22点08分

Problem E 石子游戏

现在有一个二人游戏,两人面前有一堆数量为n的小石头,两人轮流进行取小石头,每次轮到时,可以取走m个小石头,最先取光小石头的一方为胜。如果游戏的双方使用的都是最优策略,请输出哪个人能赢。
Input
输入数据为两个整数n和m(1<=n,m<=1000),n和m的含义将题目描述。
Output
根据给出的数据,如果先走的人能赢,请输出"first",否则请输出"second"
Sample Input
23 2
4 3
Sample Output
first
second
算法-Nim 游戏-(拿石头游戏)
这个最优策略是啥子嘞?举几个例子分析一下
大概就是n个石子,每次取不超过m个石子
0 &lt; n m 0&lt;n≤m 时,先手必胜
n = m + 1 n=m+1 时,先手必败
m + 2 n 2 m + 1 m+2≤n≤2m+1 时,先手必胜
n = 2 ( m + 1 ) n=2(m+1) 时,先手必败
以此类推……

#include<stdio.h>
int main(void)
{
	int n,m;//n个石子,一次取m个 
	while(scanf("%d %d",&n,&m)!=EOF){
		if(n%(m+1)!=0)
			printf("first\n");
		else
			printf("second\n");
	}
	return 0;
}

这题第一次见我估计做不出来……
2019年4月3日22点51分

Problem F 奇偶变换

对一个正整数作如下操作:如果是偶数则除以2,如果是奇数则加1,如此进行下去。求经过n(1<=n<=1000)次操作变为1的正整数有多少个?例如:经过3次操作变为1的正整数分别为2,3,8.
Input
输入数据为若干个操作数n。
Output
对于每个操作数n,输出经过n次操作变为1的正整数的个数m。
Sample Input
3
9
Sample Output
3
55

这题……不能真是枚举吧?
先吃饭,回来再想……
2019年4月5日13点10分

/*这题可以先列一下表找规律,发现每个符合题意的数字都是在1和2状态切换
*第n步为1的数,第n-1步一定为2(这一步结束后将它变为1),第n-2步结束后将它变为2
*而每一代的奇数产生只有一种可能,偶数的来源有两种
*所以F(n)=F(n-1)的奇数+2*F(n-1)的偶数,或者这么写F(n)=F(n-1)+F(n-1)的偶数个数
*这个问题可以进一步抽象,不考虑数字大小,只考虑奇偶,或者用别的什么替换 
*所以在F(n)的奇数,在F(n-1)代都为偶数,F(1)偶数个数为1,F(1)=1
*可是数值已经溢出了啊……*/
#include<stdio.h>
#include<string.h>
long long odd(long long n);
long long even(long long n);
long long even_num[1005],odd_num[1005];
int ev[1005],od[1005];
int main(void)
{
	memset(even_num,0,sizeof(long long));
	memset(odd_num,0,sizeof(long long));
	memset(ev,0,sizeof(int));
	memset(od,0,sizeof(int));
	even_num[0]=1;
	int n;
	while(scanf("%d",&n)!=EOF){
		printf("%ld\n",odd(n)+even(n));
	}
	return 0;
}
long long odd(long long n)
{
	if(n==1){
		od[1]=1;
		return odd_num[1]=0;
	}
	else if(ev[n-1]==1){
		od[n]=1;
		return odd_num[n]=even_num[n-1];
	}
	else{
		return even(n-1);
	}
}
long long even(long long n)
{
	if(n==1){
		ev[1]=1;
		return even_num[1]=1;
	}
	else if(od[n-1]==1&&ev[n-1]==1){
		ev[n]=1;
		return even_num[n]=even_num[n-1]+odd_num[n-1];
	}
	else{
		return odd(n-1)+even(n-1);
	}
}

老师说要看我的题解,试着做了一下
万万没想到,居然是记忆化搜索……
2019年4月6日10点49分

Problem G 阶乘末尾多少个0

给定一个正整数n(n<=1000000),计算这个正整数的阶乘后面有多少个0,例如8!=40320,后面有一个0.
Input
第一行输入t表示有t组测试用例,接下来输入t行,每行包括一个正整数n。
Output
对于每个测试用例,输出n!后面0的个数。
Sample Input
5
3
60
100
1024
23456
Sample Output
0
14
24
253
5861

/*Problem G 阶乘末尾多少个0
*这题我过年时好像在QQ群里看见过……当时说是计算多少个2和5就行了……
*前几天还和同学聊来着,因为2的数目足够多,只考虑5的个数就行了*/
#include<stdio.h>
int main(void)
{
	int n,x,temp;
	int i,count=0;
	scanf("%d",&n);
	while(n-->0){
		scanf("%d",&x);
		count=0;
		for(i=1;i<=x;i++){
			temp=i;
			while(temp%5==0){
				temp=temp/5;
				count++;
			}
		}
		printf("%d\n",count);
	}
	return 0;
}

2019年4月6日10点50分

Problem H 找缺失数

给定一个包含0,1,2,…,n中n个数的序列,找出0…n中没有出现在序列中的那个数。
Input
第一行表示待输入的序列数,后面每行代表一个序列
Output
每行输出序列中缺失的那个数
Sample Input
2
3 0 1
9 6 4 2 3 5 0 1 7
Sample Output
2
8

#include<stdio.h>
#include<string.h>
void quicksort(int left,int right);
int arr[1005];
int main(void)
{
	int i,n,ch;
	scanf("%d",&n);
	while(n-->0){
		memset(arr,0,sizeof(int));
		int count=0;
		while(scanf("%d",&arr[count])){
			if((ch=getchar())=='\n')
				break;
			else
				count++;
		}
		quicksort(0,count);
//		printf("\n***施工中***\n");
//		for(i=0;i<=count;i++)
//				printf("%d ",arr[i]);
//		printf("\n***施工中***\n");
		for(i=0;i<=count;i++){
			if(arr[i]!=i){
				printf("%d\n",i);
				break;
			}
		}
	}
	return 0;
}
void quicksort(int left,int right)
{
	if(left>=right) return;
	int i,j,std;
	std=arr[left];
	i=left;
	j=right;
	while(i<j){
		while(arr[j]>=std&&i<j)
			j--;
		arr[i]=arr[j];
		while(arr[i]<=std&&i<j)
			i++;
		arr[j]=arr[i];
	}
	arr[j]=std;
	quicksort(left,j-1);
	quicksort(j+1,right);
}

真是奇了怪了,每组数据的最后一项读入都会有问题……
但是又看不出代码的毛病……
2019年4月6日11点42分
然后才发现是测试数据的锅……
2019年4月6日11点51分
2019年4月3日18点21分敲完题目
要是有时间试着做一下……
B题和C题比我平时做的题难很多

附上高年级组A题

Description
There is an adventurous roller coaster which attracts all people.There are only two seats in each line in this roller coaster. Moreover ,if a girl wants to play it, she must invite a boy to be her parter.Limit by money,only the girls woth their partners can play thisgames.Caculate how many combinations(a boy and a girl) at most play this games.
Input
There are three integers, namely K,M,N, in the first line. They denote the number of possible combinations, the number o girls, and the number of boys respectively.
0<K<=1000, 1<=N,M<=500.
There are two number in each line of the following K lines.
The two numbers denote girl Ai wanting boy Bj to be her partner.
The last 0 finishes input.
Output
For each test case, output an integer which denotes the number of combinations(a boy and a girl) at most play this game.
Sample Input
6 3 3
1 1
1 2
1 3
2 1
2 3
3 1
0
Sample Output
3

猜你喜欢

转载自blog.csdn.net/Miaplacidus/article/details/88994987