#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#define gc getchar()
using namespace std;
const int N=205;
inline void qr(int &x)
{
    x=0;char c=gc;int f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=gc;}
    while(c>='0'&&c<='9'){x=x*10+(c^48);c=gc;}
    x*=f;
}
void qw(int x)
{
    if(x<0)x=-x,putchar('-');
    if(x/10)qw(x/10);
    putchar(x%10+48);
}
int d[N],e[N],f[N][N][N],c[N];
int main()
{
    int T;qr(T);
    for(int t=1;t<=T;t++)
    {
        memset(f,0,sizeof(f));
        int n,m=0;qr(n);c[0]=-1,e[0]=n;
        for(int i=1,x;i<=n;i++)
        {
            qr(x);
            if(x!=c[m])c[++m]=x,d[m]=0,e[m]=e[m-1];
            --e[m];++d[m];
        }
        for(int i=m;i;i--)
            for(int j=i;j<=m;j++)
                for(int k=0;k<=e[j];k++)//e[j]
                {
                    f[i][j][k]=f[i][j-1][0]+(d[j]+k)*(d[j]+k);//类似一种透支的东西,因为这个状态可能对答案没有贡献。 
                    for(int p=j-1;p>=i;p--)
                        if(c[p]==c[j])
                        {
                            f[i][j][k]=max(f[i][j][k],f[i][p][d[j]+k]+f[p+1][j-1][0]);
                        }
                }
        printf("Case %d: %d\n",t,f[1][m][0]);
    }
    return 0;
}
/*
思路:首先我们把每个本来相邻且颜色相同的块合并成一个大块。我们可以分区间处理,
然后尝试合并区间。然而我们发现这非常的困难,因为再加入一个新的颜色块之后,
获得子区间最优值的操作次序对当前区间可能不是最优的了。
比如后面和前面有颜色相同的两组颜色块,等他们之间3的所有颜色块合并之后他们再合并可能创造出更有解。
因此,我们不妨多加一维,记录一下区间后面有多少个颜色块与当前区间的最后一个颜色块颜色相同。
设dp[i][j][k]代表合并区间[i, j]内的颜色块,并且有k个颜色块与j颜色块相同,(这k个颜色块之间的间隔已经被消除了)。这时我们可以执行2种策略:
 
1:先把第j个颜色块和后面的k个颜色块合并了。
 
2:先不急着合并,看一看[i, j - 1]中有没有与j颜色相同的,如果有(假设这个和j颜色相同的颜色块是p),那么先把[p, j - 1]合并了。
 

*/