我正在练习这个问题,很快找到了正确的算法,但在实现它时,我遇到了一些奇怪的事情。起初,我意识到我被整数类型的溢出所困,所以开始使用__int64。那是我注意到下一个奇怪的事情。首先,这是我的代码......
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <vector>
#include <algorithm>
#include <numeric>
using namespace std;
const string cInputFileName = "E:\\CodeJamInputs\\d-large-practice.in";
const string cOutputFileName = "E:\\CodeJamInputs\\d-large-practice.out.txt";
__int64 FindSmallestProductOfSums(const vector<int> &iVec1, const vector<int> &iVec2)
{
vector<int> v1 = iVec1;
vector<int> v2 = iVec2;
sort(v1.begin(), v1.end());
sort(v2.begin(), v2.end(), greater<int>());
__int64 productOfSumsA = inner_product(v1.begin(), v1.end(), v2.begin(), 0);
__int64 productOfSumsB = 0;
for(vector<int>::size_type i = 0; i < v1.size(); ++i)
productOfSumsB += (__int64)v1[i] * (__int64)v2[i];
return productOfSumsB;
}
int _tmain(int argc, _TCHAR* argv[])
{
ifstream inputFile(cInputFileName, ifstream::in);
ofstream outputFile(cOutputFileName, ofstream::out);
if(inputFile.is_open() && outputFile.is_open())
{
int numCases;
inputFile >> numCases;
for(int i = 0; i < numCases; ++i)
{
int vectorSizes;
inputFile >> vectorSizes;
vector<int> vec1, vec2;
for(int j = 0; j < vectorSizes; ++j)
{
int value;
inputFile >> value;
vec1.push_back(value);
}
for(int j = 0; j < vectorSizes; ++j)
{
int value;
inputFile >> value;
vec2.push_back(value);
}
__int64 smallestProductOfSums = FindSmallestProductOfSums(vec1, vec2);
outputFile << "Case #" << (i + 1) << ": " << smallestProductOfSums;
outputFile << endl;
}
}
inputFile.close();
outputFile.close();
}
所以,正如你所看到的,我对这两个向量进行了两次计算。一个使用STL inner_product,另一个只是手动迭代。那么愚蠢的是,对于问题中的大数据集,inner_product方法会导致错误的返回,而这样做的方法是正确的。踩到STL代码,肯定看起来就像溢出一样,因为Ty Val变量似乎是一个int,当然这是积累的结果。
所以,我想知道的是那些使用inner_product解决了这个问题的人,您认为不同之处是什么?我尝试将0LL作为初始参数传递给giggles,实际上,它确实导致了不同的答案,但仍然不是正确的答案。奇怪的是,在添加显式__int64强制转换之前,它确实产生了与hand方法相同的答案。所以这里肯定会出现类型和溢出的奇怪现象,只是不确定是什么。无论如何,我得到的答案都适用于小型和大型套装,但我只是看到一些人使用了inner_product,我无法让它工作。让我重新说一下...... inner_product适用于小数据集,但不适用于大数据集,因为我的手解决方案适用于小型和大型集合。
以下是问题中每个案例的输出(大数据集共计10个)。对于每种情况,有三个输出。第一个是手动计算方法(正确答案),第二个是使用init为“0”的内部产品(错误答案),第三个是使用“0LL”初始化的内部产品(错误答案)。另外,仅仅是预感,我也编译为x64目标,但结果是一样的。
案例#1:-7839202227936 案例#1:-886912736 案例#1:-1104693507808
案例#2:7999201712083 案例#2:1972606931 案例#2:1127254038483
案例#3:-1313429236847 案例#3:830755729 案例#3:-175262903407
案例#4:-3710387739618 案例#4:464004126 案例#4:-89730309090
案例#5:-3414920765916 案例#5:-421765596 案例#5:-82026144220
案例#6:-1271937742993 案例#6:-627423377 案例#6:-30692194449
案例#7:-1964394407029 案例#7:-1594352757 案例#7:-40249058421
案例#8:-1884282427866 案例#8:1208215078 案例#8:-101871000026
案例#9:-4044533757860 案例#9:1325434972 案例#9:-106048747428
案例#10:-838783451371 案例#10:-1264828651 案例#10:-44214501611
对于长篇文章感到抱歉,但我认为这是一个有趣的问题。
答案 0 :(得分:0)
CPP reference包含inner_product的示例实现,如下所示:
...
value = value + *first1 * *first2;
...
inner_product涉及两种类型:
所以在你的情况下,你有一个int64用于累加器,但只有int(可能是32位数据类型)的元素。当乘法发生时,乘法的结果以32位精度计算!
因此,有两个可能的溢出位置,一个在+中,一个在*中。更改初始值会修复累加器,但在乘法中仍然存在溢出的风险。
解决此问题的最简单方法是将输入数组更改为int64而不是int的数组。在这种情况下,乘法将以64位精度完成。