问题from here:在nbAdjacent
中找到乘积最高的nStr
数字。因此,我将数字存储为字符串,并且我的代码打印出的所有内容都是正确的,但最终结果是错误的,我无法弄清楚原因...在此期间,我继续了Euler项目,但这给我带来了麻烦。
这是我的代码:
std::string nStr = "731...50"; // a 1000-digit number
uint64_t prod = 1;
int nbAdjacent = 13;
int max = 0;
for (int i = 0; i <=988; i++)
{
for (int j = 0; j < nbAdjacent; j++)
{
// yes i thought about that ;)
prod *= nStr[i + j] - '0';
}
if (prod > max)
{
max = prod;
for (int j = 0; j < nbAdjacent-1; j++)
std::cout << nStr[i + j] << " * ";
// each new max is printed
std::cout << nStr[i + nbAdjacent - 1] << " = " << prod << std::endl;
}
prod = 1;
}
它打印此:7 * 3 * 1 * 6 * 7 * 1 * 7 * 6 * 5 * 3 * 1 * 3 * 3 = 5000940
4 * 9 * 1 * 9 * 2 * 2 * 5 * 1 * 1 * 9 * 6 * 7 * 4 = 9797760
9 * 2 * 2 * 5 * 1 * 1 * 9 * 6 * 7 * 4 * 4 * 2 * 6 = 13063680
2 * 5 * 1 * 1 * 9 * 6 * 7 * 4 * 4 * 2 * 6 * 5 * 7 = 25401600
5 * 1 * 1 * 9 * 6 * 7 * 4 * 4 * 2 * 6 * 5 * 7 * 4 = 50803200
1 * 1 * 9 * 6 * 7 * 4 * 4 * 2 * 6 * 5 * 7 * 4 * 7 = 71124480
1 * 9 * 6 * 7 * 4 * 4 * 2 * 6 * 5 * 7 * 4 * 7 * 4 = 284497920
9 * 6 * 7 * 4 * 4 * 2 * 6 * 5 * 7 * 4 * 7 * 4 * 2 = 568995840
5 * 3 * 4 * 9 * 1 * 9 * 4 * 9 * 3 * 4 * 9 * 6 * 9 = 1020366720
3 * 4 * 9 * 1 * 9 * 4 * 9 * 3 * 4 * 9 * 6 * 9 * 8 = 1632586752
9 * 1 * 9 * 4 * 9 * 3 * 4 * 9 * 6 * 9 * 8 * 3 * 5 = 2040733440
8 * 6 * 9 * 4 * 7 * 8 * 8 * 5 * 1 * 8 * 4 * 3 * 8 = 2972712960
我在for循环中检查索引错误,但没有发现任何错误... 最佳答案
解决方案中的一个问题是您迭代了988
,这是不正确的,因为您将访问超出范围并包含垃圾的nStr[i + j] = nStr[988+12]=nStr[1000]
。
正如其他人指出的那样,您可以获得的最大解决方案是9^13
,它至少需要42位(log2(9^13)=41.2
),因此请使用long long int
之类的东西,在所有体系结构上都保证具有64位。
作为提示,请尝试避免在程序中对诸如988
之类的值进行硬编码,而要对其进行计算。
对于该代码,可能的改进是使用滑动窗口而不是每次都计算乘积,并跟踪乘以当前的13位数字。然后,您将每个循环迭代除以最后一位并乘以新的一位。这提供了解决方案的加速,它将是O(n)
而不是O(s*n)
。由于某些数字可能为零,因此我们可以在窗口中保留一个计数器,以了解多少个数字为0,如果此计数器> 0,我们将知道乘积为0。
这里是一个使用c++的示例解决方案,可以输出正确的结果。
#include <iostream>
#include <string>
using namespace std;
const string digits = "7316717653133062491922511967442657474235534919493496983520312774506326239578318016984801869478851843858615607891129494954595017379583319528532088055111254069874715852386305071569329096329522744304355766896648950445244523161731856403098711121722383113622298934233803081353362766142828064444866452387493035890729629049156044077239071381051585930796086670172427121883998797908792274921901699720888093776657273330010533678812202354218097512545405947522435258490771167055601360483958644670632441572215539753697817977846174064955149290862569321978468622482839722413756570560574902614079729686524145351004748216637048440319989000889524345065854122758866688116427171479924442928230863465674813919123162824586178664583591245665294765456828489128831426076900422421902267105562632111110937054421750694165896040807198403850962455444362981230987879927244284909188845801561660979191338754992005240636899125607176060588611646710940507754100225698315520005593572972571636269561882670428252483600823257530420752963450";
const int nAdj = 13;
int main()
{
int n = digits.size();
long long int prod = 1;
long long int max = 0;
int zeros = 0;
// precompute sliding window
for (int i = 0; i < nAdj-1; ++i)
{
int d = digits[i]-'0';
if(d==0) ++zeros;
else prod *= d;
}
for (int i = nAdj-1; i < n; ++i)
{
// add new digit
int d = digits[i]-'0';
if(d==0) ++zeros;
else prod *= d;
//check best
if(zeros == 0)
{
if(prod > max) max = prod;
}
//remove last digit
d = digits[i-nAdj+1]-'0';
if(d==0) --zeros;
else prod /= d;
}
cout << "The max is: " << max << endl; // 23514624000
return 0;
}