9 条题解
-
7
前言
在本地运行需要加上以下代码:
import sys sys.set_int_max_str_digits(0)
提交时需要去掉,不然会RE
这篇题解中自定义的函数如下:
plus(a:str,b:str)->str
返回 。minus(a:str,b:str)->str
返回 。multiply(a:str,b:str)->str
返回 。opposite(a:str)->str
返回 。judge(a:str,b:str)
如果 ,返回False;如果 ,返回True;如果,返回None。division(a:str,b:str,accuracy:int)->str
返回 ,保留 accuracy 位小数。rounding_down(a:str,accuracy:int)->str
返回 保留 accuracy 位小数后的结果。decimal_to_fraction(a:str)
返回转分数后的 的分母, 的整数部分, 的小数部分的分子。abs1(a:str)->str
返回 。power1(a:str,b:str,accuracy:int)->str
返回 保留 accuracy 位小数后的结果。root(a:str,b:str,accuracy:int)->str
返回 保留accuracy+int(b)*10
位小数后的结果。高精加/减/乘
众所周知,python是自带高精度的,也就是说,在进行整数的加/乘运算时不会有误差。所以我们可以先去掉小数点,然后直接用自带的+和*计算,最后在加上小数点;减去一个数等于加上这个数的相反数。这里避免抄袭,只放加法的代码:
def plus(a:str,b:str) -> str: decimal_place_a = a.find('.') decimal_place_b = b.find('.') if decimal_place_a == -1: if decimal_place_b == -1: return str(int(a)+int(b)) else: decimal_place_a = 0 elif decimal_place_b == -1: decimal_place_b = 0 if decimal_place_a != 0: decimal_place_a = len(a)-decimal_place_a-1 if decimal_place_b != 0: decimal_place_b = len(b)-decimal_place_b-1 if decimal_place_a > decimal_place_b: b += '0'*(decimal_place_a-decimal_place_b) elif decimal_place_a < decimal_place_b: a += '0'*(decimal_place_b-decimal_place_a) a = a.replace('.','',1) b = b.replace('.','',1) a = int(a) b = int(b) c = list(str(a+b)) decimal_place_c = max(decimal_place_a,decimal_place_b) minus_c = False if c[0] == '-': c.pop(0) minus_c = True if len(c) > decimal_place_c: c.insert(len(c)-decimal_place_c,'.') else: for i in range(decimal_place_c-len(c)): c.insert(0,'0') c.insert(0,'.') c.insert(0,'0') for i in range(len(c)-1,0,-1): if c[i] == '0': c.pop(i) elif c[i] == '.': c.pop(i) break else: break if minus_c and c != ['0']: c.insert(0,'-') c = ''.join(c) return c
高精度除
模拟手算即可。
def division(a:str,b:str,precision:int) -> str: minus_a = minus_b = False if a[0] == '-': minus_a = True if b[0] == '-': minus_b = True if minus_a and minus_b: return division(a[1:],b[1:],precision) elif minus_a and (not minus_b): return '-' + division(a[1:],b,precision) elif (not minus_a) and minus_b: return '-' + division(a,b[1:],precision) decimal_place_a = decimal_place_b = 0 if '.' in a: decimal_place_a = len(a.split('.')[1]) if '.' in b: decimal_place_b = len(b.split('.')[1]) # 将字符串转化为整形 num1 = a.replace('.', '') num2 = b.replace('.', '') if decimal_place_a > decimal_place_b: num2 += '0' * (decimal_place_a - decimal_place_b) elif decimal_place_a < decimal_place_b: num1 += '0' * (decimal_place_b - decimal_place_a) num1 = int(num1) num2 = int(num2) quotient = num1 // num2 # 获取小数部分 remainder = num1 % num2 decimal_place = 0 result = [] while remainder != 0 and decimal_place < precision: remainder *= 10 result.append(str(remainder // num2)) remainder = remainder % num2 decimal_place += 1 # 将结果转化为字符串 if len(result) != 0: result_str = ('.' + ''.join(result)) else: result_str = '' return str(quotient) + result_str
高精度乘方(指数为整数)
实现很简单,但可以用快速幂优化。
def power1(a:str,b:str,accuracy:int) -> str: if '.' in b: y1,y2,y3 = decimal_to_fraction(b)#res=a^b=a^(d+e/c)=a^d*(root(a,c))^e return multiply(power1(a,y2,accuracy),power1(root(a,y1,accuracy),y3,accuracy)) elif '.' not in a: return str(pow(int(a),int(b))) if b[0] == '-': return division('1',power1(a,b[1:],accuracy),accuracy) if a[0] == '-': c = '-' if '.' in b: raise ValueError('power1') if minus(multiply(division(b,'2',0),'2'),b)=='0': c = '' return c+power1(a[1:],b,accuracy) bins = list(bin(int(b))[2:]) times = len(bins) c = a if a == '0': if b == '0': return 'Error:0^0无意义' else: return '0' if b == '0': return '1' if a == '1': return '1' for i in range(1,times): c = multiply(c,c) if accuracy != -1: c = rounding_down(c,accuracy+(times-i+1)**(times-i)) if bins[i] == '1': c = multiply(c,a) if accuracy != -1: c = rounding_down(c,accuracy) return c
decimal_to_fraction函数
一个衔接函数,作用是返回转分数后的 的分母, 的整数部分, 的小数部分的分子。
from fractions import Fraction def decimal_to_fraction(a): a = Fraction(a).limit_denominator(20) b = a.numerator c = a.denominator d = b//c e = b%c return str(c),str(d),str(e)#c:分母;d:[a];e:{a}
高精度乘方(指数为有理数)
二分法:(会TLE,可能是我常数没调好)
def root(a,b,accuracy): if accuracy != 0: epsilon_max = '0.'+(accuracy-1)*'0'+'1' else: epsilon_max = '1' num = 0 #计算次数 low = '0' #下限 high = a #上限 ans = division(plus(low,high),'2',accuracy+10) #中点 epsilon = '10' while not judge(epsilon,epsilon_max): num += 1 buffer = power1(ans,b,-1) if buffer < a: low = ans else: high = ans ans = division(plus(low,high),'2',accuracy+num*num) epsilon = abs1(minus(power1(ans,b,-1),a)) return ans
牛顿迭代法(将问题转换为求方程的解):
def root(a:str,b:str,accuracy:int) -> str: #求power1(a,1/b) #x**b-y即函数f(x);b*x**(b-1)函数f(x)的导数 x = '1'+len(a)*int(division('1',b,0))*'0' #初始值 y = a num = 0 #迭代次数 if accuracy != 0: epsilon_max = '0.'+(accuracy-1)*'0'+'1' else: epsilon_max = '1' epsilon = '100' while not judge(epsilon,epsilon_max): num += 1 f_x = minus(power1(x,b,-1),y) f_x_ = multiply(b,power1(x,minus(b,'1'),-1)) x = minus(x,division(f_x,f_x_,accuracy*2+num*num)) epsilon = abs1(minus(power1(x,b,-1),y)) x = rounding_down(x,accuracy+int(b)*10) return x
后记
将以上代码结合起来即为最终代码,中间有些简单的函数就不放了
防止抄作业。以上代码均为作者手打,请勿抄袭借鉴还是可以的。
- 1
信息
- ID
- 10
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 9
- 标签
- 递交数
- 169
- 已通过
- 5
- 上传者