ACM-club预备队训练-week1(模拟与高精度、招新题)

1、h0094. 乒乓球

题目描述: 

国际乒联现在主席沙拉拉自从上任以来就立志于推行一系列改革,以推动乒乓球运动在全球的普及。

其中11分制改革引起了很大的争议,有一部分球员因为无法适应新规则只能选择退役。

华华就是其中一位,他退役之后走上了乒乓球研究工作,意图弄明白11分制和21分制对选手的不同影响。

在开展他的研究之前,他首先需要对他多年比赛的统计数据进行一些分析,所以需要你的帮忙。

华华通过以下方式进行分析,首先将比赛每个球的胜负列成一张表,然后分别计算在11分制和21分制下,双方的比赛结果(截至记录末尾)。 

比如现在有这么一份记录,(其中W表示华华获得一分,L表示华华对手获得一分): 

WWWWWWWWWWWWWWWWWWWWWWLW 

在11分制下,此时比赛的结果是华华第一局11比0获胜,第二局11比0获胜,正在进行第三局,当前比分1比1。

而在21分制下,此时比赛结果是华华第一局21比0获胜,正在进行第二局,比分2比1。

如果一局比赛刚开始,则此时比分为0比0。 

你的程序就是要对于一系列比赛信息的输入(WL形式),输出正确的结果。

输入格式:

每个输入文件包含若干行字符串(每行至多20个字母),字符串由大写的W、L和E组成。

其中E表示比赛信息结束,程序应该忽略E之后的所有内容。

输出格式:

输出由两部分组成,每部分有若干行,每一行对应一局比赛的比分(按比赛信息输入顺序)。

其中第一部分是11分制下的结果,第二部分是21分制下的结果,两部分之间由一个空行分隔。

输入样例:

WWWWWWWWWWWWWWWWWWWW
WWLWE

输出样例:

11:0
11:0
1:1

21:0
2:1

题解: 

本题关键在于如何储存输入的数据,与判断一局比赛结束的条件。

#include<iostream>

using namespace std;
int main()
{
	char x[10000],q;
	int i=0,a,b,j=0,m=0;
    
	while(cin>>x[i])             //输入数据
	{
		i++;
		if(x[i]=='E')break;
	}

	while(j<i-1)                    //11分赛制的情况
	{
		a=0,b=0;                    //a与b表示双方在每一局的得分
		for(j=m;j<=i;j++)           //循环每一回合
		{
			if(x[j]=='W')a++;
			else if(x[j]=='L')b++;
                                     //当分出胜负或检测到E时输出比分情况
			if(a>=11&&a-b>=2||b>=11&&b-a>=2||x[j]=='E')
			{
				cout<<a<<':'<<b<<endl;
				break;              //break结束本局
			}
		}
		m+=(a+b);             //每一局结束后,下一局要从数组下标m开始循环
	}
	cout<<endl;
	m=0,j=0;
	while(j<i-1)         //21分赛制的情况,接下来思路同上,不再赘述
	{
		a=0,b=0;
		for(j=m;j<=i;j++)
		{			
			if(x[j]=='W')a++;
			else if(x[j]=='L')b++;
			
			if(a>=21&&a-b>=2||b>=21&&b-a>=2||x[j]=='E')
			{
				cout<<a<<':'<<b<<endl;
				break;
			}			
		}
		m+=(a+b);
	}
	
	return 0;
}


2、高精度加法

题目描述: 

对于输入的两个不超过100位数字的非负整数,给出两数之和。

输入格式:

在两行中分别给出两个不超过100位数字的非负整数

输出格式:

在一行中输出两数之和

输入样例:

123
12

输出样例:

135

思路: 

100位数字过大,想到用数组来储存每一位数字 。本人分为了两种情况(其实应该是可以合并的)

#include<iostream>
#include<string.h>

using namespace std;
int main()
{
	char a[100],b[100];
	scanf("%s",&a);
	scanf("%s",&b);	
	int t1=strlen(a),t2=strlen(b),js=0;

	if(t1>=t2)                    //当数组a表示的数字位数更大或相等时
	{
		for(int i=t1-1;i>=0;i--,t2--)
		{
			if(t2>=1)a[i]+=b[t2-1]-'0'; //从各自的个位数开始相加
			if(a[i]>'9')                //判断是否要进位
			{
				a[i]-=10;
				if(i==0)js=1;           //标记是最大的一位数需要进位的情况
				else a[i-1]++;          //若要进位则大的一位数加一
			}		
		}
		if(js==1)cout<<"1";   /*若最大的一位数要进位,由于a[0]已经是最大的一位数,且
                               进位只可能进一,所以若进位则先输出一个1作为结果的最高位*/
		for(int m=0;m<t1;m++)cout<<a[m];
	}
	else                         //当数组b表示的数字位数更大时,下同。
	{
		for(int i=strlen(b)-1;i>=0&&t1>=1;i--,t1--)
		{			
			if(t1>=1)b[i]+=a[t1-1]-'0';
			if(b[i]>'9')
			{
				b[i]-=10;
				if(i==0)js=1;
				else b[i-1]++;
			}		
		}
		if(js==1)cout<<"1";
		for(int m=0;m<strlen(b);m++)cout<<b[m];
	}
	return 0;
}


3、高精度求累加和 

题目描述: 

使用求和公式求1到N的累加和大家都会,但是如果把N值变大呢,比如100位的整数,那该怎么求?

输入格式:

输入在一行中给出1个位数不超过100位的整数N。

输出格式:

对每一组输入,在一行中输出1+2+3+……+N的值。

输入样例:

在这里给出一组输入。例如:

10

输出样例:

在这里给出相应的输出。例如:

55

代码长度限制:16 KB

时间限制:100 ms

内存限制:64 MB

题解:

这题最恶心的地方是时间限制,对算法的要求很高,利用循环累加的算法会超时,因此必须用巧妙的算法。本人利用等差数列求和公式【(N+1)*N】/ 2  ,则接下来的难点就在于如何利用小学数学老师教咱们的竖式乘法。

#include<iostream>
#include<cstring>

using namespace std;
int main()
{
	char a[100],b[101],c[100],d[10000];  

        //数组a用于输入,数组b用来表示N+1,数组c用来表示N,数组d储存结果
        //细节:b长度定为101是考虑到输入的数可能为100位数且数字均为9,此时加一就会进位

    memset(d,'0',sizeof(d));           //初始化数组d,初始为字符0
	int i=0,js=0,flag=0,q;
	while(scanf("%c",&a[i])!='\n')
	{
		if(a[i]!='\n')i++;
		else break;
	}
	
	for(int m=i-1,j=0;m>=0;m--,j++) //逆序存放,以便进位 
	{
		b[j]=a[m];
		c[j]=a[m];
		if(c[j]!='9')flag=1;
	}
	b[0]++,b[i]='0';			//求N+1 
	int m=0,s0;
	while(b[m]>'9')             //讨论要进位的情况 
	{
		b[m]='0';
		b[++m]++;
	}							
	int t=i;
	if(flag==0)t++;				//因为当c数组表示9、99、999等等时数组b的长度就成了i+1 
	for(int j=0;j<i;j++)   
	{
		s0=0;                       //用s0表示进位时要进多少
		for(q=0;q<t;q++)
		{
			int s=(b[q]-'0')*(c[j]-'0');
			d[q+j]+=s%10+s0;
			s0=s/10;					//讨论需要进位的情况,若进位则进s0 
			while(d[q+j]>'9')           //此处不能用if,因为在此时d[q+j]-'0'有可能>=20
			{
				d[q+j]-=10;
				s0++;					
			}
		}
		if(s0!=0)d[q+j]+=s0;
	}
	
	flag=0;
	for(js=9999;js>=0;js--)
		if(d[js]!='0')break;
	for(int j=js;j>=0;j--)		                //N*(N+1)后还要除以2,且从最高位数开始除。 
	{
		if((d[j]-'0')%2==0)d[j]=(d[j]-'0')/2+'0';    //分两种情况:偶数或奇数
		else 										 
		{
			d[j]=(d[j]-'0')/2+'0';
			d[j-1]+=10;
		}
		if(d[j]!='0'||flag==1)  
		{
			cout<<d[j];
			flag=1;
		}	         //由于最高位为1时对2整除后变为0,则考虑若最高位数为0则不输出,依此类推
	}
	return 0;
}

NEUQ-ACM CLUB   2022招新题前六题:

网址:https://blog.csdn.net/swcj240031/article/details/127619113

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值