C++ 大数字的乘法和比较

C++ 大数字的乘法和比较,c++,algorithm,optimization,biginteger,C++,Algorithm,Optimization,Biginteger,我有一个问题: 有N个数字(32位)的K行。我必须选择数字的最大乘积 主要的问题是N可以上升到20。 我试着用对数来做这件事: ld sum = 0, max = 0; int index = 0; for(int i = 0; i < k; i ++) { // K lines sum = 0, c = 0; for(int j = 0; j < n; j ++) { // N numbers cin >> t; if(

我有一个问题: 有N个数字(32位)的K行。我必须选择数字的最大乘积

主要的问题是N可以上升到20。 我试着用对数来做这件事:

ld sum = 0, max = 0;
int index = 0;

for(int i = 0; i < k; i ++) { // K lines
    sum = 0, c = 0;
    for(int j = 0; j < n; j ++) { // N numbers
        cin >> t;
        if(t < 0)
            c++; // If the number is less than 0 i memorize it

        if(t == 1 || t == -1) { // if numbers = 1 OR -1
            sum += 0.00000001; // Because log(1) = 0
            if(t == -1)
                c ++;
        }
        else if(t == 0) { // if some number is equal to zero then the sum is = 0
            sum = 0;
            break;
        }
        else {
            sum += log10(fabs(t));
        }
    }

    if(c % 2 == 1) // if c is odd than multiply by -1
        sum *= -1;

    if(sum >= max) { 
        max = sum;
        index = i;
    }
    if((sum - max) < eps) { // if sum is equal to max i'm also have to choose it
        max = sum;
        index = i;
    }
}
cout << index + 1 << endl;
ld sum=0,max=0;
int指数=0;
对于(int i=0;i>t;
if(t<0)
(C++);如果数字小于0,我就记住它。
如果(t==1 | | t==1){//如果数字=1或-1
sum+=0.00000001;//因为日志(1)=0
如果(t==-1)
C++
}
否则,如果(t==0){//如果某个数等于零,则和等于0
总和=0;
打破
}
否则{
sum+=log10(fabs(t));
}
}
if(c%2==1)//如果c是奇数,则乘以-1
总和*=-1;
如果(总和>=max){
最大值=总和;
指数=i;
}
如果((sum-max)我想这句话肯定是错的:

if(c % 2 == 1) // if c is odd than multiply by -1
    sum *= -1;

如果乘积在[0,1]范围内,则其对数将为负,这将使其为正。我想你应该把它分开

如果要避免bignum libs,可以利用它,如果将
b1
b2
位数相乘,则结果是
b1+b2
位长

  • 所以只需将一行中所有乘法器的位计数相加

    • 比较一下
    • 记住数组中的结果

      int bits(DWORD p) // count how many bits is p DWORD is 32bit unsigned int
          {
          DWORD m=0x80000000; int b=32;
          for (;m;m>>=1,b--)
           if (p>=m) break;
          return b;
          } 
      
  • 索引按结果位计数降序对行进行排序

  • 如果排序后的第一个位计数也是最大值,则其行就是答案
  • 如果有多个max(更多行具有相同的位计数,并且也是max)
    • 只有这样你才能把它们相乘
  • 现在乘法运算

    • 你知道我们应该一次乘以所有的最大线
    • 每次所有子结果都可被同一素数整除
    • 除以它
    • 这样,结果将被截断为更少的位计数
    • 所以它应该适合64位的值
    • 您应该检查高达sqrt(最大值)的素数
    • 当最大值为32位时,请检查最高为65536的素数
    • 所以你可以做一个静态素数表来检查以加快速度
    • 此外,检查素数是否大于实际子结果也没有意义
    • 如果你知道怎么用埃拉托斯坦的筛子来加速
    • 但您需要在每次除法后跟踪索引偏移量,并使用周期筛选表,这有点复杂,但可行
    • 如果不检查所有素数,只检查少数选定的素数
    • 那么结果仍然会溢出
    • 所以你也应该处理它(抛出一些错误或其他东西)
    • 或者将所有子结果除以某个值,但这会使结果无效
    另一种乘法方法

    • 您还可以按值对乘法器进行排序
    • 并检查是否所有max行中都存在一些
    • 如果是,则将其更改为一个(或从列表中删除)
    • 这可以与前面的方法相结合
    bignum乘法

    • 你可以自己做bignum乘法
    • 结果是最大20*32=640位
    • 因此,结果将是无符号整数数组(位宽8,16,32…任意)
    • 您还可以将数字作为字符串处理
    • 看看这里如何计算
    • 它还包含乘法方法
    • 这里呢
    • 但对于像你这样的少数人来说,这会更慢
    • 最后,您需要比较结果
    • 所以,与MSW和LSW相比,哪一条线的数字更大,这就是最大线
    • (MSW是最重要的词,LSW是最不重要的词)

    在t==-1的情况下,您将c增加两次。

    您的程序只工作了一半的时间,您想优化它吗?首先让它工作…@Borgleader我为我的英语感到抱歉,我就是找不到合适的单词。我只是想说,也许在计算中有任何错误,或者你可以分享我可以找到信息的链接,谢谢!长双精度(我假设是typedef的值?)不足以表示您的产品。您应该使用任意精度的算术,如GMP库或Java的
    BigInteger
    类提供的算术。您是否尝试过用浮点值相乘?在现代台式PC上,您将遇到的那种环境提供了范围远远超过2^620的双精度运算。当然,要获得精确答案,您仍然需要多精度整数运算。(如果这是一项竞赛,请说明并提供链接。)(请澄清
    数字(32位)
    是什么-假设自然数,如果允许使用负整数,请说明追求的是什么:最高符号或绝对乘积。)尝试除草-剔除
    1
    的因子,产品至少包含一个
    0
    因子。考虑素数分解:计算每个素数和乘积。如果产品a中b的计数不大于或至少小于一个,则丢弃产品b。减去每个素数的最小计数。乘法和比较。@Rasul btw
    bits(x)=ceil(log2(x))=ceil(log10(x)/log10(2))=ceil(ln(x)/ln(2))
    因此它与您的方法类似,但仅适用于整数算术