Thinking:
1. Sort the sticks from the longest to the shortest.
2. Among those small sticks, we start from the largest one Smax. The length of the complete stick L should range from Smax to (Sum of sticks),and Sum%L == 0
AC code:
#include<iostream>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
bool cmp(const int a,const int b)
{
return a > b;
}
int stk[70];
bool used[70];
int per;// L
int n;
bool check_validity(int remain,int n_stk,int now_stk)// remain: how long do we need to complete current stick
{//n_stk: how many sticks should be assembled
//now_stk :the stick chosen last time
if(n_stk== 1)// if there is only one stick left to be complete, then it's perfect
return true;
if(remain == per)//start of a new stick
{
int k = 1;
while(used[k]) k++;// find the largest unused stick
used[k] = true;
if(check_validity(remain-stk[k],n_stk,k))//assemble
return true;
used[k] = false;
return false;
}
else if(remain == 0)//finished the assembling of a stick
return check_validity(per,n_stk-1,1);//start next one
else
{
for(int i = now_stk+1;i <= n;i++)
{
if(!used[i]&&(remain-stk[i] >=0))// choose unused ones and remain should be larger than the stk
{
if(!used[i-1]&&stk[i] == stk[i-1])continue;// **important if the stk[j] failed and stk[j+1] == stk[j],it is unnecessary to try j+1
used[i] = true;
if(check_validity(remain-stk[i],n_stk,i))
return true;
used[i] = false;
}
}
return false;
}
}
int main()
{
while(scanf("%d",&n)&&n)
{
for(int i = 1;i <= n;i++)
scanf("%d",&stk[i]);
sort(stk+1,stk+1+n,cmp);
int maxx = stk[1];
int sum(0);
bool flag =false;
for(int i = 1;i <= n;i++)
sum+=stk[i];
for(int i = maxx;i <= sum/2;i++)
{
memset(used,false,sizeof(used));
if(sum % i == 0)
{
per = i;
if(check_validity(i,sum/i,1))
{
flag = true;
printf("%d\n", i);
break;
}
}
}
if(!flag)
printf("%d\n",sum);
}
return 0;
}