#include #include using namespace std; vector > memo; int gcd(int a, int b){ while(b != 0){ int temp = b; b = a%b; a = temp; } return a; } void Rotate(const vector& orig, vector& copy, int amount){ for(int i = 0; i < copy.size(); i++){ copy[i] = orig[(i+amount)%orig.size()]; } } // What is the cost of removing the sequence from x to y? x will be the last // element remaining in the range. int Solve(const vector& sequence, int x, int y){ if(memo[x][y] !=-1) return memo[x][y]; if(x+1 == y){ memo[x][y] = gcd(sequence[x], sequence[y]); return memo[x][y]; } if(x >=y) return 0; int best = 100*100; // the element at position x will be the last thing to go. // find the second to last thing for(int i = x+1; i <= y; i++){ int temp = Solve(sequence, x,i-1) + Solve(sequence, i,y) + gcd(sequence[x], sequence[i]); if(temp < best) best = temp; } memo[x][y] = best; return best; } void Print_Vector(const vector& v){ for(int i = 0; i < v.size(); i++) cout << v[i] << " "; cout << endl; } int main(){ int cur_case = 1; int n; cin >> n; while(n >0){ memo.resize(n); for(int i = 0; i < n; i++) memo[i].resize(n); vector sequence(n); for(int i = 0; i < n; i++) cin >> sequence[i]; int best= 100*100; for(int i = 0; i < n; i++){ vector temp_sequence(n); // rotate the sequence so that element i is first. It's more efficient // to do this with clever indec offsets, but this is esier. Rotate(sequence, temp_sequence, i); // add a copy of the first element to the end to aid wrapping around temp_sequence.push_back(temp_sequence[0]); for(int j = 0; j < n; j++) for(int k = 0; k < n; k++) memo[j][k] = -1; // Print_Vector(temp_sequence); int cur = Solve(temp_sequence,0,n-1); if(cur < best) best = cur; } cout << "Case " << cur_case <<": " << best << endl; cur_case++; cin >> n ; } return 0; }