我正在尝试解决Problem 13 @ Project Euler,我正在寻找一个好的算法来做添加并输出非常大的数字的答案。首先,我将数字的数字转换为矩阵的元素(100 x 50)。这是我提出的算法:
unsigned long long int sum=0, carry_over=0;
for(int j=49; j>=0; j--)
{
for(int i=0; i<100; i++)
sum+=num[i][j];
sum+=carry_over;
carry_over=sum/10;
cout<<sum%10;
sum=0;
}
cout<<carry_over;
现在,输出将有反转的数字,从单位放置数字开始,最后是总和的第一个数字。这很容易手动逆转。
我想知道这是一个好的算法,考虑准确性和速度。请建议更正以改善它。
答案 0 :(得分:0)
您的算法已经是最优的。
您的算法的时间复杂度为O(m*n)
,其中m
是每个数字中的位数(50),n
是数字的数量(100),以及#39; s输入中的数字位数。很容易看出你必须从输入中读取所有数字才能输出正确的答案,所以你必须至少阅读m*n
位数,给出时间复杂度O(m*n)
只是用于读取输入。因此,算法的时间复杂度不能低于此值,因此您的O(m*n)
算法是最佳的。
如果不知何故,你已经在RAM中(并以合适的格式)输入数据,你可以考虑其他一些优化。
考虑地址大小:
现代计算机的地址大小为32或64位,这意味着它们可以在一次操作中对32位或64位进行加法。 64位是大约18个十进制数字,因此存储每个整数所需的3个64位整数,因此加法的时间复杂度将从m=50
减少到m=3
,从而得到求和快一个数量级。
考虑并行处理:
现代计算机可以并行运行多个线程。这个问题的解决方案很容易并行化。如果您的机器能够同时运行2个线程,您可以使用第一个线程对前50个数字求和,使用第二个线程对第二个50进行求和。在两个总和完成之后(如果在一个线程上计算所有内容,大约需要一半的时间),您只需将两个子结果相加。