《编程思维与实践》1012.平衡三进制I

文章介绍了如何处理平衡三进制表示中的整数和小数部分,通过迭代方法转换数字,并特别讨论了小数部分的处理,包括最大公约数的使用以及特殊情况下正负数的调整规则。代码示例展示了具体的实现过程。
摘要由CSDN通过智能技术生成

《编程思维与实践》1012.平衡三进制I

题目

在这里插入图片描述
在这里插入图片描述

思路

先将读入的数据分别取出整数部分和小数部分,整数部分同之前的题目一样迭代即可,关键在于小数部分的处理。

注意到 k 1 ⋅ 3 − 1 + k 2 ⋅ 3 − 2 + . . . + k n ⋅ 3 − n = k 1 ⋅ 3 n − 1 + k 2 ⋅ 3 n − 2 + . . . + k n 3 n k_1·3^{-1}+k_2·3^{-2}+...+k_n·3^{-n}=\frac{k_1·3^{n-1}+k_2·3^{n-2}+...+k_n}{3^n} k131+k232+...+kn3n=3nk13n1+k23n2+...+kn

同时分子 k 1 ⋅ 3 n − 1 + k 2 ⋅ 3 n − 2 + . . . + k n = 3 ( k 1 ⋅ 3 n − 2 + k 2 ⋅ 3 n − 3 + . . . + k n − 1 ) + k n k_1·3^{n-1}+k_2·3^{n-2}+...+k_n=3(k_1·3^{n-2}+k_2·3^{n-3}+...+k_{n-1})+k_n k13n1+k23n2+...+kn=3(k13n2+k23n3+...+kn1)+kn

故分子也可以通过迭代进行处理,之后只需要再将分子和分母约分(同除以最大公约数)即可.

注意的点:

考虑小数部分的最大情况(k全取1),结果是 3 − 1 + 3 − 2 + . . . + 3 − n = 3 − 1 − 3 − ( n + 1 ) 1 − 3 − 1 = 1 − 3 − n 2 < 1 3^{-1}+3^{-2}+...+3^{-n}=\frac{3^{-1}-3^{-(n+1)}}{1-3^{-1}}=\frac{1-3^{-n}}{2}<1 31+32+...+3n=131313(n+1)=213n<1,即不可能出现假分数;

因为平衡三进制包含-1,故分数部分处理结果可能小于0,

故需要对以下特殊情况单独考虑:

1.整数部分大于0,结果应该满足 A p q = A + ∣ p q ∣ A\frac{p}{q}=A+|\frac{p}{q}| Aqp=A+qp,

2 − 1 9 应改为 1 8 9 = 1 + 8 9 2-\frac{1}{9}应改为1\frac{8}{9}=1+\frac{8}{9} 291应改为198=1+98,

2.整数部分小于0,结果应该满足 A p q = − ( ∣ A ∣ + ∣ p q ∣ ) A\frac{p}{q}=-(|A|+|\frac{p}{q}|) Aqp=(A+qp),

− 2 + 1 9 -2+\frac{1}{9} 2+91 应改为 − 1 8 9 = − ( 1 + 8 9 ) -1\frac{8}{9}=-(1+\frac{8}{9}) 198=(1+98), 而 − 2 + − 1 9 = − ( 2 + 1 9 ) -2+\frac{-1}{9}=-(2+\frac{1}{9}) 2+91=(2+91) 则满足条件.

但还需注意如果 − 1 + 1 9 = − 8 9 -1+\frac{1}{9}=\frac{-8}{9} 1+91=98, 即分子变化后还应再变为相反数.

代码

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<math.h>

int gcd(long long a,long long b)      //求最大公因数 
{
	if(a<b)
	{
		int temp=a;
		a=b;
		b=temp;
	}
	if(a%b)
	{
		return gcd(b,a%b);
	}
	return b;
}

int main()
{
	char s[31];                 //长度最大30
	int i=0;
	long long A=0;              //整数部分用long long   
	scanf("%s",s);               //  最终变成 A p/q 形式 
	while(isdigit(s[i]))
	{
        A=(s[i]=='2')?A*3-1:A*3+s[i]-'0';
		i++; 
	} 
	
	if(s[i]=='.')   //有小数部分
	{
		i++;
        long long p=0,q=1;
		while(isdigit(s[i]))
		{
			q*=3;
			p=(s[i]=='2')?p*3-1:p*3+s[i]-'0';
			i++;
		} 
		p=p/gcd(abs(p),q);            //p有可能小于0
		q=q/gcd(abs(p),q);
		
		if(A>0&&p<0){
			A-=1;
			p=q+p;
		}
		
		if(A<0&&p>0)
		{
			A+=1;
			p=q-p;
            if(A==0)
            {
                p*=-1;
            }
		}
		
		if(A==0)    //整数部分为0不输出
		{
			printf("%lld %lld",p,q);
		}
		
		else
		{
			printf("%lld %lld %lld",A,p,q);
		}
	}
    
	else
	{
		printf("%lld",A);
	}
	return 0;
} 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值