<span>蓝桥杯——基础训练(二)</span>
特殊的数字(循环+判断+数位)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 153是一个非常特殊的数,它等于它的每位数字的立方和,即153=111+555+333。编程求所有满足这种条件的三位十进制数。
输出格式
- 按从小到大的顺序输出满足条件的三位十进制数,每个数占一行。
AC
#include <stdio.h>
int main(){
int i,g,s,b;
for(i=100;i<1000;i++){
g=i%10%10; //个位
s=i/10%10; //十位
b=i/100; //百位
if(i==g*g*g+s*s*s+b*b*b) printf("%d\n",i);
}
return 0;
}
回文数(循环+判断+回文数)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 1221是一个非常特殊的数,它从左边读和从右边读是一样的,编程求所有这样的四位十进制数。
输出格式
- 按从小到大的顺序输出满足条件的四位十进制数。
思考
- 将每个数的位数两层循环打印出来。
AC
#include <stdio.h>
int main(){
int i,j;
for(i=1;i<=9;i++){
for(j=1;j<=9;j++){
printf("%d%d%d%d\n",i,j,j,i);
}
}
return 0;
}
特殊回文数(回文数+循环+条件语句)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 123321是一个非常特殊的数,它从左边读和从右边读是一样的。
- 输入一个正整数n, 编程求所有这样的五位和六位十进制数,满足各位数字之和等于n 。
输入格式
- 输入一行,包含一个正整数n。
输出格式
- 按从小到大的顺序输出满足条件的整数,每个整数占一行。
样例输入
- 52
样例输出
899998
989989
998899
数据规模和约定
- 1<=n<=54。
AC
#include <stdio.h>
int main(){
int i,j,k,n;
scanf("%d",&n);
for(i=1;i<=9;i++) //所有这样的五位十进制数
for(j=0;j<=9;j++)
for(k=0;k<=9;k++)
if(n==(i+j)*2+k)
printf("%d%d%d%d%d\n",i,j,k,j,i);
for(i=1;i<=9;i++) //所有这样的六位十进制数
for(j=0;j<=9;j++)
for(k=0;k<=9;k++)
if(n==(i+j+k)*2)
printf("%d%d%d%d%d%d\n",i,j,k,k,j,i);
return 0;
}
十进制转十六进制(循环+整除+求余+判断)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 十六进制数是在程序设计时经常要使用到的一种整数的表示方式。它有0,1,2,3,4,5,6,7,8,9,A,B,C,D,E,F共16个符号,分别表示十进制数的0至15。十六进制的计数方法是满16进1,所以十进制数16在十六进制中是10,而十进制的17在十六进制中是11,以此类推,十进制的30在十六进制中是1E。
- 给出一个非负整数,将它表示成十六进制的形式。
输入格式
- 输入包含一个非负整数a,表示要转换的数。0<=a<=2147483647
输出格式
- 输出这个整数的16进制表示
样例输入
- 30
样例输出
- 1E
思考
- 十进制转化为十六进制计算方式,简单说就是整数除以16取余,直到商为0为止,然后从最后一个余数读到第一个。
- 注意0的存在!!!
AC
#include <stdio.h>
int main(){
int n,i,str[100],num=0;
scanf("%d",&n);
if(n==0) printf("%d",n); //如果为0,16进制仍为 0
while(n!=0){ //计算每一位的余数,存入数组
int fs=n;
n=n/16;
str[num++]=fs%16;
}
for(i=num-1;i>=0;i--){ //逆序输出
if(str[i]>9 && str[i]<16)
printf("%c",str[i]-10+'A');
else
printf("%d",str[i]);
}
printf("\n");
return 0;
}
十六进制转十进制(进制转换+字符处理+判断)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 从键盘输入一个不超过8位的正的十六进制数字符串,将它转换为正的十进制数后输出。
- 注:十六进制数中的10~15分别用大写的英文字母A、B、C、D、E、F表示。
样例输入
- FFFF
样例输出
- 65535
思考
- 十六进制转换成十进制的具体算法是:
- 首先明白16进制数(从右到左数是第0位,第1位,第2位……)的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方,依次这样排列下去。
- 明白ABCDEF表示的二进制数字分别是10,11,12,13,14,15。
- 十六进制转换成十进制的公式是:要从右到左用二进制的每个数去乘以16的相应次方,然后这些数字相加就是了。
例1:2AF5换算成10进制:
第0位: 5 * 16^0 = 5
第1位: F * 16^1 =15*16^1= 240
第2位: A * 16^2= 10* 16^2=2560
第3位: 2 * 16^3 = 8192
结果就是:5 * 16^0 + 15 * 16^1 + 10 * 16^2 + 2 * 16^3 = 10997
例2:CE换算成10进制:
第0位:E*16^0=14*16^0=14
第1位:C*16^1=12*16^1=192
结果就是:14*16^0+12*16^1=206
- 错了三次,只要还是细节问题,在<kbd>-‘0’</kbd>时,变成了<kbd>+</kbd>。
- 调用了两个函数,
绝对值函数pow(),求字符串长度的函数strlen()
,如果不用函数,也可以,但代码会有点长。 - 本题也有陷阱,也是出在数据范围上,不超过8位的十六进制数,所以计算总和的sum应该声明为long型,而不是int型,否则会出错。
AC
#include <stdio.h>
#include <math.h> //调用pow()函数
#include <string.h> //调用strlen()函数
int main(){
long long y=0;
int i;
char x[8];
scanf("%s",x);
for(i=0;i<strlen(x);i++){
if(x[i]<'0'+10){ //单个字符小于10即当字符为数字时
y += (x[i]-'0')*pow(16,strlen(x)-1-i);
}else{ //当字符为字母时
y += (x[i]-'A'+10)*pow(16,strlen(x)-1-i);
}
}
printf("%lld\n",y);
return 0;
}
十六进制转八进制(进制转换+字符+循环)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 给定n个十六进制正整数,输出它们对应的八进制数。
输入格式
- 输入的第一行为一个正整数n (1<=n<=10)。
- 接下来n行,每行一个由09、大写字母AF组成的字符串,表示要转换的十六进制正整数,每个十六进制数长度不超过100000。
输出格式
- 输出n行,每行为输入对应的八进制正整数。
【注意】
- 输入的十六进制数不会有前导0,比如012A。
- 输出的八进制数也不能有前导0。
样例输入
2
39
123ABC
样例输出
71
4435274
【提示】
- 先将十六进制数转换成某进制数,再由某进制数转换成八进制。
思考
- 100000位的十六进制数,这么大的数不好直接处理,先将十六进制数转换成二进制数,再由二进制数转换成八进制。
- 使用c++中的string库解决此问题
- 注意前导0的输出
测试数据 39
十六进制 0011 1001
不够三的倍数 +0(使用string中的t=”00”+t非常方便)
加0后 000 111 001
输出八进制 0 7 1此时的前导0 去电
结果 71
AC
#include<iostream>
#include<string>
using namespace std;
int main(){
int n,i,k,len,flag,sum;
string s,t;
cin>>n;
for (k=0;k<n;k++) {
cin>>s;
t="";//字符串的初始化
for (i=0;i<s.length();i++) {
switch(s[i]) {
case '0':t+="0000";break;
case '1':t+="0001";break;
case '2':t+="0010";break;
case '3':t+="0011";break;
case '4':t+="0100";break;
case '5':t+="0101";break;
case '6':t+="0110";break;
case '7':t+="0111";break;
case '8':t+="1000";break;
case '9':t+="1001";break;
case 'A':t+="1010";break;
case 'B':t+="1011";break;
case 'C':t+="1100";break;
case 'D':t+="1101";break;
case 'E':t+="1110";break;
case 'F':t+="1111";break;
}
}
len=t.length();
if(len%3==1){//16进制转换成2进制后填0
t="00"+t;
}else if(len%3==2) {
t="0"+t;
}
flag=0;
for (i=3;i<=t.length();i+=3) {
sum=(t[i-3]-'0')*4+(t[i-2]-'0')*2+t[i-1]-'0';
if(sum)//控制第一次的前导不为0
flag=1;
if(flag)
cout<<sum;
}
cout<<endl;
}
return 0;
}
- 直接使用java自带的方法去转就行了,不过值得注意的是,因为是先从16进制转为10进制,再从10进制转为8进制,所以要用BigInteger,防止爆0
import java.math.BigInteger;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
sc.nextLine(); // 换行
for (int i = 0; i < n; i++) {
// 从16转10再转8
System.out.println(new BigInteger(sc.nextLine(),16).toString(8));
}
}
}
数列排序(数组+排序)
资源限制
- 时间限制:1.0s 内存限制:512.0MB
问题描述
- 给定一个长度为n的数列,将这个数列按从小到大的顺序排列。1<=n<=200
输入格式
- 第一行为一个整数n。
- 第二行包含n个整数,为待排序的数,每个整数的绝对值小于10000。
输出格式
- 输出一行,按从小到大的顺序输出排序后的数列。
样例输入
5
8 3 6 4 9
样例输出
3 4 6 8 9
思考
- 自定义一个qsort()函数,因为C中没有C++中的sort()函数。
AC
#include <stdio.h>
int cmp(const void *a,const void *b){
return *(int*)a-*(int*)b;
}
int main(){
int n,i,str[10010];
scanf("%d",&n);
for(i=0;i<n;i++){
scanf("%d",&str[i]);
}
qsort(str,n,sizeof(str[0]),cmp);
for(i=0;i<n;i++){
printf("%d ",str[i]);
}
return 0;
}
因为不是VIP,所以官网的题库的基础训练部分就只能写到这。虽然其它网站也有原题,但官网的OJ更合适。