试解PTA《20211122-函数基础练习》,涉及 高精度加法 和 10进制转换成2-16进制问题,有需要的同学来看看吧;

目录

一、前言

二、例题部分

       2.1、进制转换 

2.1.1、题解1

  2.1.2、题解2

2.2、 函数返回一个整数的反序数 (20 分)

2.2.2 题解

2.3、 大整数A+B (10 分)

2.3.1 题解

2.4 求组合数 (16 分)

2.4.1 题解

三、尾声



一、前言

        您好,我是夏日弥,叫我“夏”或者“小弥”都可以。

        本次带来每周例行PTA测试讲解。

        将涉及 高精度加法10进制转换成2-16进制 问题。

        让我们来看看今天的5道题。

二、例题部分

       2.1、进制转换 

将十进制整数n(−231≤n≤231−1)转换成k(2≤k≤16)进制数。注意,10~15分别用字母A、B、C、D、E、F表示。

输入格式:

首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试数据输入两个整数n和k。

输出格式:

对于每组测试,先输出n,然后输出一个空格,最后输出对应的k进制数。

输入样例:

4
5 3
123 16
0 5
-12 2

输出样例:

5 12
123 7B
0 0
-12 -1100

2.1.1、题解1

         因为涉及11~16进制转换,要用到A、B、C、D、E、F字母,所以我们要用字符串来解决这个问题:

        首先,我们编一个万能的进制转换函数,类型为string型。

        我们用 t=n%进制数 来获取最后一位数t,如十进制123取3;

        再用 n/=进制数  来销毁最后一位数,如十进制的123销毁3,变成12;

        小tips:t为int型,要转化为char型,可以这么做

         t+‘0’ 比如说 t=1 ,1+‘0’ = ‘1’;

        ans+= ‘1’;

        如果t>10,就 t-10 + ‘A’ ;10 - 10 + ‘A’ = ‘A’;

        ans+= ‘A’; 

string intToA(int n,int radix)    
{
    string ans="";	//定义空的字符串ans; 
    do{
        int t=n%radix;	//取该进制的最后一位,比如十进制的123中的3; 
        if(t>=0&&t<=9)    ans+=t+'0';//如果该进制的最后一位数是0~9,则直接加入ans;t为int型,t+'0'被转化为char型; 
        else ans+=t-10+'A';//如果该进制的最后一位数是比9大,则转化为相应的进制表示,如10转为A,11转为B等等;
        n/=radix;//销毁最后一位,如123销毁3变成12; 
    }while(n!=0);//用do-while确保输入为0时返回ans="0";    
    reverse(ans.begin(),ans.end());//string类的子函数,反转字符串的元素,如321反转成123; 
    return ans; //返回ans; 
}

        然后呢,特化判断输入的值小于0的情况:

        只需要在其绝对值结果前加一个‘-’号就可以了;

#include<bits/stdc++.h>
using namespace std;
string intToA(int n,int radix)    
{
    string ans="";	//定义空的字符串ans; 
    do{
        int t=n%radix;	//取该进制的最后一位,比如十进制的123中的3; 
        if(t>=0&&t<=9)    ans+=t+'0';//如果该进制的最后一位数是0~9,则直接加入ans;t为int型,t+'0'被转化为char型; 
        else ans+=t-10+'A';//如果该进制的最后一位数是比9大,则转化为相应的进制表示,如10转为A,11转为B等等;
        n/=radix;//销毁最后一位,如123销毁3变成12; 
    }while(n!=0);//用do-while确保输入为0时返回ans="0";    
    reverse(ans.begin(),ans.end());//string类的子函数,反转字符串的元素,如321反转成123; 
    return ans; //返回ans; 
}
int main(){
	int n=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		int num,k;
		scanf("%d %d",&num,&k);
		if(num>=0)cout<<num<<" "<<intToA(num,k)<<endl;
		else cout<<num<<" -"<<intToA(num*-1,k)<<endl;
	}
}

  2.1.2、题解2

        准备逃课!

        来看这个函数!

        它被包含在这个头文件#include<stdlib.h>

        itoa(num,s,k);//num为整形int或long,s为字符数组,k为想要转化的进制数;

返回类型为string;

#include<bits/stdc++.h>
using namespace std;
int main(){
	int num,k;
	char s[100];
	cin>>num>>k;
	cout<<itoa(num,s,k);//num为整形int或long,s为字符数组,k为想要转化的进制数 
}

        但是它输出为11进制等的数时,输出的11为‘a’而不是'A';

所以我们写一个小循环替换大小写;

        最终答案为:

        

#include<bits/stdc++.h>
using namespace std;
string intToA(int n,int radix)    
{
    string ans=""; 
    do{
        int t=n%radix; 
        if(t>=0&&t<=9)    ans+=t+'0';  
        else ans+=t-10+'a';
        n/=radix; 
    }while(n!=0);    
    reverse(ans.begin(),ans.end());
    return ans;     
}
int main(){
	int n=0;
	scanf("%d",&n);
	for(int i=0;i<n;i++){
		int num,k;
		char s[999];
		scanf("%d %d",&num,&k);
		
		switch(k){
			case 2:{
				itoa(num,s,2);
				printf("%s",s);
				break;
			}
			case 3:{
				itoa(num,s,3);
				printf("%s",s);
				break;
			}
			case 4:{
				itoa(num,s,4);
				printf("%s",s);
				break;
			}
			case 5:{
				itoa(num,s,5);
				printf("%s",s);
				break;
			}
			
			case 6:{
				itoa(num,s,6);
				printf("%s",s);
				break;
			}
			case 7:{
				itoa(num,s,7);
				printf("%s",s);
				break;
			}
			case 8:{
				itoa(num,s,8);
				printf("%s",s);
				break;
			}
			case 9:{
				itoa(num,s,9);
				printf("%s",s);
				break;
			}
			
			case 10:{
				itoa(num,s,10);
				printf("%s",s);
				break;
			}
			case 11:{
				itoa(num,s,11);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
			case 12:{
				itoa(num,s,12);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
			case 13:{
				itoa(num,s,13);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
			case 14:{
				itoa(num,s,14);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
			case 15:{
				itoa(num,s,15);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
			case 16:{
				itoa(num,s,16);
				for(int i=0;s[i];i++){
					if(s[i]>='a'&&s[i]<='z')s[i]+=('A'-'a');
				}
				printf("%s",s);
				break;
			}
		}
	}
}

2.2、 函数返回一个整数的反序数 (20 分)

编写函数返回形式参数(一个正整数)的反序数。主函数功能为:输入一个整数N,输出N的反序数。

输入样例:

21000

结尾无空行

输出样例:

12

结尾无空行

输入样例:

1234

结尾无空行

输出样例:

4321

结尾无空行

2.2.2 题解

        

#include<bits/stdc++.h>
using namespace std;
int rev(int x){
	int a[1000],i=0,sum=0;
	while(x!=0)
	{
		a[i]=x%10;
		i++;
		x/=10;
	}
	for(int j=0;j<i;j++){
		sum+=a[j];
		sum*=10;
	}
	sum/=10;
	return sum;
}



int main(){
	int n;
	cin>>n;
	cout<<rev(n);
}

参照2.1的解法,注意因为我们是数组是倒序记录的,所以用这个方法写就可以了

for(int j=0;j<i;j++){
		sum+=a[j];
		sum*=10;
	}
	sum/=10;
	return sum;

来看看vector吗

#include<bits/stdc++.h>
using namespace std;
int main(){
	long long int sum=0,n;
	vector<int> a;
	cin>>n;
	while(n!=0){
		a.push_back(n%10);
		n/=10;
	}
	for(auto x:a){
		sum+=x;
		sum*=10;
	} 
	cout<<sum/10;
} 

之后会为感兴趣的同学讲vector;

2.3、 大整数A+B (10 分)

输入两个整数A、B,求 A + B。

输入格式:

首先输入一个正整数T,表示测试数据的组数,然后是T组测试数据。每组测试输入2个正整数A、B。整数可能很大,但每个整数的位数不会超过1000。

输出格式:

对于每组测试输出两行数据;第一行输出"Case #:",#表示测试组号,第二行输出形式为“A + B = Sum”,Sum表示A+B的结果。每两组测试数据之间空一行。

输入样例:

2
1 2
88888888888888888888888 11111111111111111111111

输出样例:

Case 1:
1 + 2 = 3

Case 2:
88888888888888888888888 + 11111111111111111111111 = 99999999999999999999999

出处:

HDOJ 1002

2.3.1 题解

#include<bits/stdc++.h>
using namespace std;
string P  (string & num,string add){
    int g=0;
    if(num.length()<add.length()){
        string t=num;
        num=add;
        add=t;
    }//如果num的长度小于add的长度,则交换num和add的内容; 
    string t (num.length()-add.length(),'0');
    add= t+add;//在数字头部补全add的长度,使其与num一样长;如123补全为000123; 
    int len1=num.length(),len2=add.length();
    for(int i=len1-1;i>=0;i--){
        int t=((num[i]-'0') +(add[i]-'0') + g);//模拟竖式,g为进制; 
        num[i]=t%10+'0';//从低位开始计算; 
        g=t/10;//记录进制是否为空; 
    }
    if(g!=0){
        num.insert(0,string(1,(char)g+'0'));
    }//判断头部进制; 
    return num;
}
int main(){
	int n,n1=1,p=0;
	cin>>n;
	for(int i=0;i<n;i++){
		string a,b,c;
		cin>>a>>b;
		c=a;
		if(p!=0)cout<<endl<<endl;
		p=1;
		printf("Case %d:\n",n1);
		n1++;
		cout<<c<<" + "<<b<<" = "<<P(a,b);
	}
} 

可以用相同的思路来编写高精度减法,高精度乘法,高精度除法;

救命!

2.4 求组合数 (16 分)

本题要求编写程序,根据公式Cnm​=m!(n−m)!n!​算出从n个不同元素中取出m个元素(m≤n)的组合数。

建议定义和调用函数fact(n)计算n!,其中n的类型是int,函数类型是double

输入格式:

输入在一行中给出两个正整数m和n(m≤n),以空格分隔。

输出格式:

按照格式“result = 组合数计算结果”输出。题目保证结果在double类型范围内。

输入样例:

2 7

结尾无空行

输出样例:

result = 21

结尾无空行

2.4.1 题解

#include<bits/stdc++.h>
using namespace std;
double fact(int n){
	if(n>=1)return fact(n-1)*n;
	else return 1;
}
int main(){
	int n,m;
	double sum=0;
	cin>>m>>n;
	sum=(fact(n))/((fact(m))*fact(n-m));
	printf("result = %.lf",sum);
}

水题,大家自己玩!

三、尾声

         感谢您的阅读;

        下次小夏会为您讲解一些基础的STL知识,期待您的阅读。

             特别鸣谢hasmokan提供的封面图;

                                                                                                                                  夏日弥死傲娇

                                                                                                                                        2021.11.22

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值