蓝桥杯刷题一

题目来源:蓝桥杯ACM训练系统
题目编号1468~1479

1.报时助手

题目描述

给定当前的时间,请用英文的读法将它读出来。时间用时h和分m表示,在英文的读法中,读一个时间的方法是:如果m为0,则将时读出来,然后加上“o’clock”,如3:00读作“three o’clock”。如果m不为0,则将时读出来,然后将分读出来,如5:30读作“five thirty”。时和分的读法使用的是英文数字的读法,其中0~20读作:0:zero, 1: one, 2:two, 3:three, 4:four, 5:five, 6:six, 7:seven, 8:eight, 9:nine, 10:ten, 11:eleven, 12:twelve, 13:thirteen, 14:fourteen, 15:fifteen, 16:sixteen, 17:seventeen, 18:eighteen, 19:nineteen, 20:twenty。30读作thirty,40读作forty,50读作fifty。对于大于20小于60的数字,首先读整十的数,然后再加上个位数。如31首先读30再加1的读法,读作“thirty one”。按上面的规则21:54读作“twenty one fifty four”,9:07读作“nine seven”,0:15读作“zero fifteen”。

输入

输入包含两个非负整数h和m,表示时间的时和分。非零的数字前没有前导0。h小于24,m小于60。

输出

输出时间时刻的英文。

样例输入

0 15

样例输出

zero fifteen

#include<bits/stdc++.h>
using namespace std;
string nums[]={"zero","one","two","three","four","five","six","seven","eight","nine","ten","eleven","twelve","thirteen","fourteen","fifteen","sixteen","seventeen","eighteen","nineteen","twenty"};
int h,m;
void duShi(int h)
{
    if(h<=20)
        cout<<nums[h]<<" ";
    else
        cout<<nums[20]<<" "<<nums[h-20]<<" ";
}
void duFen(int m)
{
    if(m==0)
        cout<<"o'clock"<<endl;
    else if(m<=20)
        cout<<nums[m]<<endl;
    else
    {
        int shi=m-(m%10);
        int ge=m%10;
        if(shi==20)
            cout<<"twenty";
        else if(shi==30)
            cout<<"thirty";
        else if(shi==40)
            cout<<"forty";
        else if(shi==50)
            cout<<"fifty";
        if(ge!=0)
            cout<<" "<<nums[ge]<<endl;
        else
            cout<<endl;
    }
}
int main() {
    cin>>h>>m;
    duShi(h);
    duFen(m);
    return 0;
}

2.数的读法

题目描述

Tom教授正在给研究生讲授一门关于基因的课程,有一件事情让他颇为头疼:一条染色体上有成千上万个碱基对,它们从0开始编号,到几百万,几千万,甚至上亿。比如说,在对学生讲解第1234567009号位置上的碱基时,光看着数字是很难准确的念出来的。所以,他迫切地需要一个系统,然后当他输入12 3456 7009时,会给出相应的念法:十二亿三千四百五十六万七千零九用汉语拼音表示为shi er yi san qian si bai wu shi liu wan qi qian ling jiu这样他只需要照着念就可以了。你的任务是帮他设计这样一个系统:给定一个阿拉伯数字串,你帮他按照中文读写的规范转为汉语拼音字串,相邻的两个音节用一个空格符格开。注意必须严格按照规范,比如说“10010”读作“yi wan ling yi shi”而不是“yi wan ling shi”,“100000”读作“shi wan”而不是“yi shi wan”,“2000”读作“er qian”而不是“liang qian”。

输入

有一个数字串,数值大小不超过2,000,000,000。

输出

是一个由小写英文字母,逗号和空格组成的字符串,表示该数的英文读法。

样例输入

1234567009

样例输出

shi er yi san qian si bai wu shi liu wan qi qian ling jiu

#include<iostream>
#include<string>
using namespace std;
int main()
{
    string a[12]={"ling","yi","er","san","si","wu","liu","qi","ba","jiu","shi"};//创建一个每个数字所对应的拼音的字符串
    string b[9]={"shi","bai","qian","wan","shi","bai","qian","yi","shi"};
    int n,x,i,j,c[10],num;
    while(cin>>n)//循环输入
    {
        if(n==0)//判断是否输入的是0,如果是的话直接输出,不用循环
        {
            cout<<"ling"<<endl;
            continue;
        }
        x=0,num=0,i=0;
        while(n/10!=0)
        {
            c[x++]=n%10;
            n=n/10;
        }
        c[x]=n;//把输入的n的各位数字放入到数组中
        for(i=x;i>0;i--)
        {
            if(c[i]==0)//0和不是0的分开判断
            {
                num++;//计算0的个数
                if(i!=0)
                {
                    if(c[i]==0&&c[i-1]!=0)
                        cout<<"ling ";//防止多输出“ling”
                }
            }
            else if(c[i]==1&&i%4==1)//为了输出类似“十万”而不是“一十万”
            {
                cout<<"shi"<<" ";
            }
            else cout<<a[c[i]]<<" "<<b[i-1]<<" ";
        }
        if(c[i]!=0)
            cout<<a[c[i]];//个位数字是0的话不用输出
        else 
            num++;
        if(num==x&&num>4&&num%4>=1)
            cout<<b[num-2];//对应输出“200000”这种除去首位之外全是零的数字
        cout<<endl;
    }
    return 0;
}
// 来源:https://blog.dotcpp.com/a/62175

3.矩形面积交

题目描述

平面上有两个矩形,它们的边平行于直角坐标系的X轴或Y轴。对于每个矩形,我们给出它的一对相对顶点的坐标,请你编程算出两个矩形的交的面积。

输入

输入仅包含两行,每行描述一个矩形。 在每行中,给出矩形的一对相对顶点的坐标,每个点的坐标都用两个绝对值不超过10^7的实数表示。

输出

输出仅包含一个实数,为交的面积,保留到小数后两位。

样例输入

1 1 3 3 2 2 4 4

样例输出

1.00

#include <bits/stdc++.h>
 
using namespace std;
 
class point         //定义"点"类,可用大小为2的数组代替
{
public:
    double x;
    double y;
};
 
bool mycheck(point a, point b)              //函数:判断点a是否在点b左下方
{
    return (a.x < b.x && a.y < b.y);
}
 
int main()
{
    double x[4];                //记录输入的横坐标
    double y[4];                //记录输入的纵坐标
 
    point a1, a2, b1, b2;       //定义矩阵A与B的左下和右上端点,1为左下,2为右上
 
    for (int i = 0; i < 4; i++)     //循环输入
    {
        cin >> x[i] >> y[i];
    }
    //寻找两矩阵的左下右上端点
    a1.x = fmin(x[0], x[1]), a1.y = fmin(y[0], y[1]);
    a2.x = fmax(x[0], x[1]), a2.y = fmax(y[0], y[1]);
 
    b1.x = fmin(x[2], x[3]), b1.y = fmin(y[2], y[3]);
    b2.x = fmax(x[2], x[3]), b2.y = fmax(y[2], y[3]);
 
    double ans = 0;             //定义答案
    if (mycheck(b1, a2) && mycheck(a1, b2))     //判断是否重合
    {
        sort(x, x + 4);                         //横坐标排序
        sort(y, y + 4);                         //纵坐标排序
        ans = (x[2] - x[1]) * (y[2] - y[1]);    //计算答案
    }
    printf("%.2f\n", ans);                      //输出
    return 0;
}
//来源:https://blog.dotcpp.com/a/77089

4.矩阵乘法

题目描述

给定一个N阶矩阵A,输出A的M次幂(M是非负整数)例如:A =1 23 4A的2次幂7 1015 22

输入

第一行是一个正整数N、M(1< =N< =30, 0< =M< =5),表示矩阵A的阶数和要求的幂数 接下来N行,每行N个绝对值不超过10的非负整数,描述矩阵A的值

输出

输出共N行,每行N个整数,表示A的M次幂所对应的矩阵。相邻的数之间用一个空格隔开

样例输入

2 2 1 2 3 4

样例输出

7 10 15 22

#include<bits/stdc++.h>
using namespace std;
int N,M;
int nums[35][35];	//原矩阵
int res[35][35];	//每次乘积后的矩阵
int jisuan(int x,int y)	//根据xy坐标计算出矩阵乘积中xy位置的结果
{
	int sum=0;
	for (int i = 0; i < N; i++)
	{
		sum+=res[x][i]*nums[i][y];	//每次乘积得到的矩阵相应行乘原矩阵相应列
	}
	return sum;
}
int main()
{
    cin>>N>>M;
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			cin>>nums[i][j];
			res[i][j]=nums[i][j];
		}		
	}
	
	//0或1为特殊情况专门处理
	if(M==0||M==1)
	{
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				if(M==0)	//0次幂就是单位矩阵,对角线为1其余为0
				{
					if(i==j)
						cout<<1<<" ";
					else
						cout<<0<<" ";
				}		
				else	//1次幂就是原矩阵本身
					cout<<nums[i][j]<<" ";	
			}	
			cout<<endl;
		}
		return 0;
	}

	//一般情况计算乘积
	int cnt=M;
	while(cnt!=1)	//注意2次幂只做一次乘
	{
		int temp[35][35];	//temp临时矩阵存放临时乘积
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				temp[i][j]=jisuan(i,j);
			}	
		}
		//计算出临时矩阵每个位置的值后赋值给res矩阵
		for (int i = 0; i < N; i++)
		{
			for (int j = 0; j < N; j++)
			{
				res[i][j]=temp[i][j];
			}	
		}
		cnt--;
	}

	//输出结果
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			cout<<res[i][j]<<" ";
		}	
		cout<<endl;
	}
    return 0;
}

5.芯片测试

题目描述

有n块芯片,有好有坏,已知好芯片比坏芯片多。每个芯片都能用来测试其他芯片。用好芯片测试其他芯片时,能正确给出被测试芯片是好还是坏。而用坏芯片测试其他芯片时,会随机给出好或是坏的测试结果(即此结果与被测试芯片实际的好坏无关)。给出所有芯片的测试结果,问哪些芯片是好芯片。

输入

输入数据第一行为一个整数n,表示芯片个数。

第二行到第n+1行为n*n的一张表,每行n个数据。表中的每个数据为0或1,在这n行中的第i行第j列(1≤i, j≤n)的数据表示用第i块芯片测试第j块芯片时得到的测试结果,1表示好,0表示坏,i=j时一律为1(并不表示该芯片对本身的测试结果。芯片不能对本 身进行测试)。

(2≤n≤20)

输出

按从小到大的顺序输出所有好芯片的编号

样例输入

3 1 0 1 0 1 0 1 0 1

样例输出

1 3

#include<bits/stdc++.h>
using namespace std;
int nums[30][30];
bool isBad[30];
int n;
int main()
{
    cin>>n;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cin>>nums[i][j];
		}		
	}
	//对每列遍历,如果每个物品在所有测试结果中坏的个数大于一半那它一定是坏的(好芯片多)
	for (int i = 0; i < n; i++)
	{
		int sum=0;
		for (int j = 0; j < n; j++)
		{
			if(i==j)
				continue;
			if(nums[j][i]==0)
				sum++;
			if(sum>n/2)
				isBad[i]=true;
		}		
	}

	for (int i = 0; i < n; i++)
	{
		if(!isBad[i])
			cout<<i+1<<" ";
	}
	
    return 0;
}

6.阶乘计算

题目描述

输入一个正整数n,输出n!的值。其中n!=123*…*n。算法描述n!可能很大,而计算机能表示的整数范围有限,需要使用高精度计算的方法。使用一个数组A来表示一个大整数a,A[0]表示a的个位,A[1]表示a的十位,依次类推。将a乘以一个整数k变为将数组A的每一个元素都乘以k,请注意处理相应的进位。首先将a设为1,然后乘2,乘3,当乘到n时,即得到了n!的值。

输入

输入包含一个正整数n,n< =1000。

输出

输出n!的准确值。

样例输入

10

样例输出

3628800

#include<bits/stdc++.h>
using namespace std;
int A[3000],jin[3000];
int n,temp;
int nums=1;//记录结果数字位数  
int main()
{
    cin>>n;
    A[0]=1;
    for (int i = 2; i <= n; i++)    //遍历每个乘数
    {
        memset(jin,0,sizeof(jin));  //将jin位数组清零
        for (int j = 0; j < nums; j++)  //遍历A的每一位
        {  
            temp=A[j]*i+jin[j]; //临时记录每一位与乘数相乘加上前一位的进位
            if(temp>=10)
            {
                jin[j+1]=temp/10;   //若有进位保留到jin[j+1]
                if(j==nums-1)   //如果当前是A的最高位且乘积大于等于10才拓展位数
                    nums++;
            }
            A[j]=temp%10;
        } 
    }
    for (int i = nums-1; i >= 0; i--)
    {
        cout<<A[i];
    }
    return 0;
}

看了下别人的题解,优化了下代码,去掉了进位数组用一个int类型变量来记录进位

#include<bits/stdc++.h>
using namespace std;
int nums=1,n,temp,jin;
int a[3000];
int main(){
    cin>>n;
    a[0]=1;
    for(int i=2;i<=n;i++)   //对每个乘数
    {  
        for(int j=0;j<nums;j++) //对A数组的每一位
        {   
            temp=a[j]*i+jin;    //临时记录每一位与乘数相乘加上前一位的进位
            a[j]=temp%10;   
            jin=temp/10;    //记录进位
            
            //如果当前是A的最高位且乘积大于等于10才拓展位数
            if(j==nums-1&&temp>=10)
                nums++;
        }
    }
    for (int i = nums-1; i >= 0; i--)
    {
        cout<<a[i];
    }
    return 0;
}

7.龟兔赛跑预测

题目描述

话说这个世界上有各种各样的兔子和乌龟,但是 研究发现,所有的兔子和乌龟都有一个共同的特点——喜欢赛跑。于是世界上各个角落都不断在发生着乌龟和兔子的比赛,小华对此很感兴趣,于是决定研究不同兔 子和乌龟的赛跑。他发现,兔子虽然跑比乌龟快,但它们有众所周知的毛病——骄傲且懒惰,于是在与乌龟的比赛中,一旦任一秒结束后兔子发现自己领先t米或以 上,它们就会停下来休息s秒。对于不同的兔子,t,s的数值是不同的,但是所有的乌龟却是一致——它们不到终点决不停止。然而有些比赛相当漫长,全程观看会耗费大量时间,而小华发现只要在每场比赛开始后记录下兔子和乌龟的数据——兔子的速度v1(表示每秒兔子能跑v1 米),乌龟的速度v2,以及兔子对应的t,s值,以及赛道的长度l——就能预测出比赛的结果。但是小华很懒,不想通过手工计算推测出比赛的结果,于是他找 到了你——清华大学计算机系的高才生——请求帮助,请你写一个程序,对于输入的一场比赛的数据v1,v2,t,s,l,预测该场比赛的结果。

输入

输入只有一行,包含用空格隔开的五个正整数v1,v2,t,s,l,其中(v1,v2< =100;t< =300;s< =10;l< =10000且为v1,v2的公倍数)

输出

输出包含两行,第一行输出比赛结果——一个大写字母“T”或“R”或“D”,分别表示乌龟获胜,兔子获胜,或者两者同时到达终点。 第二行输出一个正整数,表示获胜者(或者双方同时)到达终点所耗费的时间(秒数)。

样例输入

10 5 5 2 20

样例输出

D 4

#include<bits/stdc++.h>
using namespace std;
int v1, v2, t, s, l;
int s1,s2,rest;
int main() {
    cin >> v1 >> v2 >> t >> s >> l;
    while (++rest) {
        s1 += v1;
        s2 += v2;
        if (s1 == l && s2 == l) 
        {
            cout << "D" << endl << rest << endl;
            return 0;
        } 
        else if (s1 == l) 
        {
            cout << "R" << endl << rest << endl;
            return 0;
        } 
        else if (s2 == l) 
        {
            cout << "T" << endl << rest << endl;
            return 0;
        }
        //关键代码,如果s1领先s2至少t米,就直接让兔子后退v1*s米
        //之后的循环每秒兔子再往前走v1米,经过s秒可以回到原来领先的位置
        //所以也就等效于兔子等待s秒的效果
        if (s1 - s2 >= t) {
            s1 -= v1 * s;
        }
    }
    return 0;
}
//来源:https://blog.dotcpp.com/a/67808

8.字符串输入输出函数

题目描述

编写函数GetReal和GetString,在main函数中分别调用这两个函数。在读入一个实数和一个字符串后,将读入的结果依次用printf输出。两次输入前要输出的提示信息分别是" please input a number:\n”和" please input a string:\n"

样例输入

9.56 hello

样例输出

please input a number: please input a string: 9.56 hello

//题目很简单,但题目给的有问题,写的时候直接复制的提示信息一直提示格式错误
//看别人的题解原来是题目给的提示每个单词之间有两个空格,而实际留一个空格就行
//感觉这题目样例输出也有点问题,题目说的是每次输入前有提示,而样例先把两个两个提示输出了😓
#include<bits/stdc++.h>
using namespace std;
double n;
string s;
void GetReal()
{
    cout<<"please input a number:\n";
    cin>>n;
}
void GetString()
{
    cout<<"please input a string:\n";
    cin>>s;
}
int main() {
    GetReal();
    GetString();
    cout<<n<<endl;
    cout<<s<<endl;
    return 0;
}

9.3000米排名预测

题目描述

3000米长跑时,围观党们兴高采烈地预测着 最后的排名。因为他们来自不同的班,对所有运动员不一定都了解,于是他们分别对自己了解的一些运动员的实力作出了评估,即对部分运动员做了相对排名的预 测,并且告诉了可怜留守的班长。因为无聊,于是他们就组团去打Dota去了。比赛结束后他们向班长询问最后的排名,但班长不记得了,只记得他们中哪些人的 预测是正确的,哪些人的预测是错误的。他们想知道比赛的排名可能是什么。

输入

第一行两个整数n, m,n为运动员数量,m为围观党数量。运动员编号从0到n-1。

接下来m行,每行为一个围观党的相对排名预测。每行第一个数c表示他预测的人数,后面跟着c个0~n-1的不同的数,表示他预测的运动员相对排名,最后还有一个数,0表示这个预测是错误的,1表示是正确的。

数据规模和约定 1< =n< =10, 2< =c< =n, 1< =m< =10,保证数据合法,且答案中排名可能数不超过20000。对于一个排名序列,一个预测是正确的,当且仅当预测的排名的相对顺序 是排名序列的一个子序列。一个预测是错误的,当且仅当这个预测不正确。

输出

第一行一个数k为有多少种排名的可能。 下面k行,每行一个0~n-1的排列,为某一个可能的排名,相邻的数间用空格隔开。所有排名按字典序依次输出。

样例输入

3 2 2 0 1 1 2 1 2 0

样例输出

2 0 2 1 2 0 1

#include<bits/stdc++.h>
using namespace std;
int n,m;
int arr[10][11]; //每个吃瓜群众的猜测
int flag[10];//每个吃瓜群众的猜测的正确性
int player[10];//运动员的编号
int sum;//记录多少种可行排名的数目
string str;//记录所有可能的排列

//核心函数,判断排列是否满足题意
//设两个指针分别遍历预测数列和要判断的数列,看哪个指针先走到头
bool judge(int p[]) //数组 p 是需要判断的一个排列
{
    int i,j,k;  //循环变量
    int num;   //num表示吃瓜群众对几个运动员预测了成绩
    for(i = 0; i < m; i++)  //循环每个吃瓜群众的预测成绩
    {
        num = arr[i][0];  //赋值,arr[i][0]是吃瓜群众作了几个预测
        for(j = 1,k = 0; j < num && k < n;k++)  // 逻辑:需要了解是相对位置,所以遍历整个排列,如果 j 先结束则说明序列是统一的;  如果k先结束则说明序列是不统一的。
        {
            if(arr[i][j] == p[k])
            {
                j++;
            }
        }
        if(j >= num && !flag[i]) //预测正确(flag[i] = 1), 则看是否全排列等于该预测结果,不一致,则该排列不正确, reture false
                                //预测错误(flag[i] = 0), 则看是否全排列等于该预测结果, 一致,   则该排列不正确, return false
            return false;
        if(k >= n && j < num && flag[i])
            return false;
    }
    return true;
}
void out(int p[])
{   do
    {
        if(judge(p))
        {
            for(int i = 0; i < n; i++)
            {
                str+=p[i] + '0';
                str+=' ';
            }
            sum++;
            str[str.size() - 1] = '\n';
        }
    }while(next_permutation(p,p+n));
}
int main()
{
    int c;
    cin >> n >> m;

    for(int i = 0; i < n; i++)
        player[i] = i;
    for(int i = 0; i < m; i++)
    {
        cin >> c;
        arr[i][0] = c + 1;
        for(int j = 1; j < c + 1; j++)
            cin >> arr[i][j];
        cin >> flag[i];  
    }
    out(player);
    cout << sum << endl;
    cout << str;
    
    return 0;
}

10.删除数组中的0元素

题目描述

编写函数CompactIntegers,删除数组中所有值为0的元素,其后元素向数组首端移动。注意,CompactIntegers函数需要接收数组及其元素个数作为参数,函数返回值应为删除操作执行后数组的新元素个数。输入时首先读入数组长度,再依次读入每个元素。将调用此函数后得到的数组和函数返回值输出。

输入

第一行一个数,表示数组个数

第二行为每个数字,空格分开

输出

输出处理后的数字以及个数,各占一行

样例输入

7 2 0 4 3 0 0 5

样例输出

2 4 3 5 4

#include<bits/stdc++.h>
using namespace std;
int CompactIntegers(int nums[],int n)
{
    int index=0;
    for (int i = 0; i < n; i++)
    {
        if(nums[i]!=0)
        {
            nums[index]=nums[i];    //用index重新填充非零元素
            index++;
        }
    }
    return index;  
}
int main()
{
	int n;
    cin>>n; 
    int nums[n];
    for (int i = 0; i < n; i++)
    {
        cin>>nums[i];
    }
    int newNums=CompactIntegers(nums,n);
	  for (int i = 0; i < newNums; i++)
    {
        cout<<nums[i]<<" ";
    }
    cout<<endl<<newNums<<endl;
	return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值