特殊的数字(循环+判断+数位)

资源限制

  • 时间限制: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

思考

  • 十六进制转换成十进制的具体算法是:
  1. 首先明白16进制数(从右到左数是第0位,第1位,第2位……)的第0位的权值为16的0次方,第1位的权值为16的1次方,第2位的权值为16的2次方,依次这样排列下去。
  2. 明白ABCDEF表示的二进制数字分别是10,11,12,13,14,15。
  3. 十六进制转换成十进制的公式是:要从右到左用二进制的每个数去乘以16的相应次方,然后这些数字相加就是了。
12AF5换算成10进制:0位: 5 * 16^0 = 51位: F * 16^1 =15*16^1= 2402位: A * 16^2= 10* 16^2=25603位: 2 * 16^3 = 8192
结果就是:5 * 16^0 + 15 * 16^1 + 10 * 16^2 + 2 * 16^3 = 109972:CE换算成10进制:0位:E*16^0=14*16^0=141位: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非常方便)
加0000 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更合适。