《编程思维与实践》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} k1⋅3−1+k2⋅3−2+...+kn⋅3−n=3nk1⋅3n−1+k2⋅3n−2+...+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 k1⋅3n−1+k2⋅3n−2+...+kn=3(k1⋅3n−2+k2⋅3n−3+...+kn−1)+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 3−1+3−2+...+3−n=1−3−13−1−3−(n+1)=21−3−n<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} 2−91应改为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+9−1=−(2+91) 则满足条件.
但还需注意如果 − 1 + 1 9 = − 8 9 -1+\frac{1}{9}=\frac{-8}{9} −1+91=9−8, 即分子变化后还应再变为相反数.
代码
#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;
}