C++ 大数字的乘法和比较
我有一个问题: 有N个数字(32位)的K行。我必须选择数字的最大乘积 主要的问题是N可以上升到20。 我试着用对数来做这件事: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(
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 btwbits(x)=ceil(log2(x))=ceil(log10(x)/log10(2))=ceil(ln(x)/ln(2))
因此它与您的方法类似,但仅适用于整数算术