【ACM算法】-- 数学问题篇 - 进制转换

谁都会走 提交于 2020-02-15 01:50:42

第一题:
在这里插入图片描述
思路: 对于进制转换问题,其实理解了取模运算和 10 进制运算,基本是特别好理解的,在进制转换问题中,只需掌握,m 进制转换为 10 进制,10 进制转换为 n 进制即可,任何进制之间的转换,都已 10 进制为桥梁,这样的话,所有的进制题,都可以抽象成 10 进制转换问题。

理解: 在十进制中,我们要获得每一位的数值,需要数位拆解,每拆完一位,然后缩小目标数,再拆一位,取模运算中,产生的位一定不会超过模,仔细想一下,这就相当于把一个数改成模这种大小的一种进制,每缩一圈,都会产生一位。但是数值总大小是真正不会变的。这时候,我们不妨把一个数抽象成 数X,对于X这个数,现在他没有任何进制的表示,如果想要用10进制来表示,则对10取模,再缩小,再取模。如果想用2进制来表示,则对2取模。(注意:当数X本身就用2进制或其他进制来表示的时候,这时候的取当前进制数的模就变成了数位拆解。)以下就是更加疯狂地个人理解了:当其他进制向十进制转变的时候,需要位乘位权,这个过程是m进制先转换为数X,数X再转换为10进制,只不过,数X在现实世界中的表现形式与10进制相符合,所以这时候数X在转换成10进制,就相当于数位拆解了。
综上,忽略以上扯淡理解,就可以把数X就看成十进制数。这时候十进制数就是核心。由它负责向其他进制转换,而其他进制相互转换也必须经过十进制。当然像计组里面的2进制直接转16进制啥的,在ACM中一般不会考虑。

代码如下:

对于int 、long 之间的使用:链接

#include<stdio.h>
int ans[21];

int main(){
	int m;
	long long a,b;//因为说了不超过整数范围,但是如果都是最大值,那么一相加就溢出了,所以用longlong类型
	freopen("in.txt","r",stdin);
	while(scanf("%d%lld%lld",&m,&a,&b)!=EOF&&m!=0){
		int size=0;
		long long tmp=a+b;//对于longlong类型的,如果输出,要用printf("%lld\n",tmp);其他的报错
		do{
			ans[size++]=tmp%m;
			tmp/=m;
		}while(tmp!=0);//注意此处数位拆解,用的是do while循环,是为了防止0的出现而拆解不了
		for(int i=size-1;i>=0;i--)
		printf("%d",ans[i]);
		printf("\n");
	}
	return 0;
}

错误代码:

以下这段代码的错误之处一般很少能看出来,我当初想的是,既然 a 和 b 的范围都相当于大数,我又防止它溢出,所以用求模公式,这个代码在求模这里是没错的,错就错在了除法上,按照数学逻辑来说,(a+b)/m = a/m+b/m ,但是计算机中的除法是默认向下取整的,这时候,需要用浮点数,但是这就涉及到精度问题了,可能除完之后再相加,由于精度丢失问题,得不到理想的理论结果。

#include<stdio.h>
int ans[21];

int main(){
	int m,a,b;
	freopen("in.txt","r",stdin);
	while(scanf("%d%d%d",&m,&a,&b)!=EOF&&m!=0){
		int size=0;
		while(a!=0||b!=0){
			ans[size++]=(a%m+b%m)%m;
			a/=m;b/=m;//此处错误,但是思想是新颖的,只不过用在这里不对
		}
		for(int i=size-1;i>=0;i--)
		printf("%d",ans[i]);
		printf("\n");
	}
	return 0;
}

第二题:
在这里插入图片描述
思想:这个思想就很简单了,主要就是进制转换,首先转成10进制,再由10进制转为其他进制。

代码如下:

#include<stdio.h>
#include<string.h>
int main(){
	int a,b;
	char s[50],ans[50];
	freopen("in.txt","r",stdin);
	while(scanf("%d%s%d",&a,s,&b)!=EOF){
		int len=strlen(s);
		int weight=1;
		long res=0;
		for(int i=len-1;i>=0;i--){
			int tmp=0;
			if(s[i]>='A'&&s[i]<='Z'){
				tmp=10+(s[i]-'A');
			}else if(s[i]>='a'&&s[i]<='z'){
				tmp=10+(s[i]-'a');
			}else{
				tmp=s[i]-'0';
			}
			res+=tmp*weight;
			weight*=a;
		}
		int size=0;
		do{
			int t=res%b;
			ans[size++]=t<10?t+'0':'A'+(t-10);
			res/=b;
		}while(res!=0);
		for(int i=size-1;i>=0;i--){
			printf("%c",ans[i]);
		}
		printf("\n");
	}
	return 0;
}
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!