一个很妙的Python题,但我找不到好的解法

这是我自己编的题目)这个我做出来了,在相对比较正常的数据中我的算法没有问题,但是我的算法不知道有什么问题,在数据输入等于1E+32的时候结果中的分母为0了,在大于1E+32的时候会出现负数,不知道有没有人能解释一下,或者说给出更好的解题方法
题目链接:https://www.luogu.com.cn/problem/U194217
题目的大致描述是:

现代数学的著名证明之一是 Georg Cantor 证明了有理数是可枚举的。他是用下面这一张表来证明这一命题的:
【这里有个表我弄不出来,请到链接里查看,谢谢!】
输入格式
一个整数N
数据较大的话会输入科学计数法表示的形式
如:1E+20
输出格式
表中第N项
说明/提示
数据范围:
对于30%的数据:0<N<=1E+7(10的7次方)
对于100%的数据:0<N<=1E+30(10的30次方)
时间限制:
TimeLimit = 20ms(二十毫秒)

对比大数decimal计算与int计算,int有误差;看下面的代码,都是40个零,不要用科学计数法。

import decimal as di 
def Out(m):
    di.getcontext().prec=200
    n=(di.Decimal(-1)+di.Decimal(1+8*m).sqrt())/di.Decimal(2) 
    n =di.Decimal(int(di.Decimal(n)) + 1)
    s = n * (n + di.Decimal(1.0)) / di.Decimal(2.0)    
    t = s-m+1
    print('n', n)
    print('s', s)
    print('t', t)
    if n%2==0:
        return(f'{n-t+1}/{t}')
    else:
        return(f'{t}/{n-t+1}')

x = Out(10000000000000000000000000000000000000000)
print('result', x)    

def out(m):
    n=int((-1+(1+8*m)**0.5)/2)+1
    s = (1+n)*n//2
    t = s-int(m)+1
    print('n', n)
    print('s', s)
    print('t', t)
    if n%2==0:
        return(f'{n-t+1}/{t}')
    else:
        return(f'{t}/{n-t+1}')

print(out(10000000000000000000000000000000000000000))


def solve(n):
    # find first r that (1+r)*r/2 >= n
    lo, hi = 0, n
    while lo < hi:
        mid = (lo+hi) >> 1
        if (((1+mid)*mid) >> 1) < n:
            lo = mid + 1
        else:
            hi = mid
    
    # the order in the Diagonal 
    order = n - (((hi-1)*hi)>>1)
    if hi & 1:
        return f"{hi+1-order}/{order}"
    else:
        return f"{order}/{hi+1-order}"

import time
e15 = 1000000000000000
e20 = 100000000000000000000

t=time.time()
print(solve(7))
print(time.time()-t)

t=time.time()
print(solve(e15))
print(time.time()-t)

t=time.time()
print(solve(e20))
print(time.time()-t)

1/4
0.00020432472229003906
2235880/42485481
0.0010771751403808594
3266133124/10876002501
0.0001857280731201172
注意,输入不能是科学计数法,因为科学计数法是浮点数,转换成整数的时候会变得不相等。
比如 int(1E+23) 得到的是 99999999999999991611392,负数的出现也是同样的原因。

超过大数变化应该是编码问题,比如uft-8编码2字节,存储数据超过字节编码就发生移位就出现了0和负数。换个编码试试。

import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int ans = 1;//计算的是第几项
int i = 1;//i代表的是分子也就是行数
int j = 1;//j代表的是分母也就是列数
int temp = 1;//1代表遍历的方向是向上的,0代表遍历的方向是向下的
int n = scanner.nextInt();

    while(n!=ans) {//如果你没有判断到最后一项的话就继续判断,一个一个枚举的判断
        if(temp==1) {//如果方向向上
            if(i==1) {//判断是否到了上边缘
                j++;//分母加1,像右边前进一格
                temp=0;//改变方向
                ans++;//判断下一项
                continue;//方向改变了就要退出当前循环,进行下一次的判断
            }else {//没有到上边缘
                i--;//分子减1
                j++;//分母加1
            }
        }else {
            if(j==1) {//判断是否到了左边缘
                i++;//分子加1,像下走一格
                temp=1;//改变方向
                ans++;//判断下一项
                continue;//方向改变了就要退出当前循环,进行下一次的判断
            }else {//没有到左边缘
                i++;//分子加1
                j--;//分母减1
            }
        }
        ans++;//没有抵达边缘的判断结束后,都要加1
    }
    System.out.println(i+"/"+j);
    scanner.close();
}

}

def Out(m):
    n = int(m**0.5)
    m = int(m)
    while (1+n)*n//2<m:
        n += 1
    t = (1+n)*n//2-m+1
    if n%2==0:
        return(f'{n-t+1}/{t}')
    else:
        return(f'{t}/{n-t+1}')

import time

t=time.time()
print(Out(7))
print(time.time()-t)

t=time.time()
print(Out(1E+15))
print(time.time()-t)

输出结果:
1/4
0.010000228881835938
2235880/42485481
3.6888062953948975

如时间不满足要求,更快的办法直接解方程 n*n+n-2*m=0
n=(-1+(1+8*m)**0.5)/2,负根舍去,然后取整

def Out(m):
    n=int((-1+(1+8*m)**0.5)/2)+1
    t = (1+n)*n//2-int(m)+1
    if n%2==0:
        return(f'{n-t+1}/{t}')
    else:
        return(f'{t}/{n-t+1}')

import time

t=time.time()
print(Out(7))
print(time.time()-t)

t=time.time()
print(Out(1E+15))
print(time.time()-t)

输出结果:
1/4
0.015600204467773438
2235880/42485481
0.015599727630615234
15毫秒满足要求了!