const int PN = 10000000;
int primes[PN];
vector<int> primelist;
void sieve() {
primes[0] = 0;
primes[1] = 0;
primes[2] = 1;
for (int i = 3; i < PN; ++i)
primes[i] = i % 2;
for (int i = 3; i <= int(sqrt(PN*1.0) + 0.5); i += 2)
if (primes[i])
for (int j = 2*i; j < PN; j += i)
primes[j] = 0;
for (int i = 0; i < PN; ++i)
if (primes[i])
primelist.push_back(i);
}
//这个函数的目的是生成素数表,并把素数表添加到Primelist中
void sum(int n, vector<int>& out) {
if (primelist.size() < n) return;
int cursum = accumulate(primelist.begin(), primelist.begin() + n, 0);
out.push_back(cursum);
for (int l = 0, r = n; r < primelist.size(); ++r, ++l) {
cursum += primelist[r] - primelist[l];
out.push_back(cursum);
}
}
//把所有的n个连续素数的和保存到out中
int main()
{
sieve();
vector<int> sums[12];
sums[0] = primelist;
//copy(primelist.begin(), primelist.begin() + 20, ostream_iterator<int>(cout, " "));
int N; cin >> N;
for (int I = 1; I <= N; ++I)
{
int m; cin >> m;
for (int i = 1; i <= m; ++i)
{
int tmp; cin >> tmp;
sums[i].clear();
sum(tmp, sums[i]);
}
//把结果保存到了sums数组中
int ni[12] = { 0 };
bool success = false;
int result = 0;
while (!success)
{
for (int i = 0; i <= m; ++i)
{
result = max(result, sums[i][ni[i]]);
}
for (int i = 0; i <= m; ++i)
{
while (sums[i][ni[i]] < result)
++ni[i];
}
success = true;
for (int i = 0; i <= m; ++i)
{
if (sums[i][ni[i]] != result)
success = false;
}
}
//这里很巧妙,用了现行推进的算法每次找到最小,同时向前推进.如果最小不相同则又从刚结束的问题推进
cout << "Scenario " << I << ":" << endl;
cout << result << endl << endl;
}
}
很好的一个问题,这个思想真的很重要.首先构造出所有n个连续数和,然后利用一个O(n)的算法找到我们所要求的最小值!