解题思路: 每次取最大木棍和最小木棍比较,若相等,则所有木棍长度相等,完成;否则将最大木棍一分为二,更新最小木棍。重复直至完成。
    木棍实现:用结构体保存木棍一分为二的两种可能(L为奇数时),每次取木棍时尽量取其中奇数木棍(奇数和偶数相差1,奇数一分为二后有的两种长度包含了偶数一分为二后的长度)。
#include<cstdio>
#include<queue>
using namespace std;

const int INF = 1e9+1;

struct stick
{/*结构体保存每个木棍的可能*/
	int l , r;
	/*运算符重载*/ 
	bool operator <(const stick &s)const
	{
		if( l==s.l )
		{
			return r<s.r;
		}
		return l<s.l;
	}
	bool operator ==(const stick &s)const
	{
		return ( (l==s.l) || (l==s.r) || (r==s.l) || (r==s.r) );
	}
};

int main()
{
	int n,L;
	stick s,min_s;//min_s保存最小木棍 
	priority_queue<stick> que; //默认为大顶堆 每次取出最大木棍 
	min_s.l = min_s.r = INF;
	
	scanf("%d",&n);
	for( int i=0; i<n; i++ )
	{
		scanf("%d",&L);
		s.l = s.r = L;
		if( s<min_s )	min_s = s;
		que.push(s);
	}
	
	int res = 0;
	while( true )
	{
		s = que.top(); que.pop(); //每次取出最大木棍
		if( min_s==s )
			break; //所有木棍都一样长 退出
		
		if( s.l&1 )	L = s.l;//(奇,偶);(奇,奇);(偶,奇);(偶,偶) 
		else		L = s.r;//(偶,偶)时相同,所以只在l为奇时取 
		/*最大木棍一分为二后的长度*/ 
		if( L&1 )
		{
			s.l = L/2;
			s.r = L/2+1;	
		} 
		else
		{
			s.l = s.r = L/2;
		}
		
		if( s<min_s )	min_s = s;//更新最小木棍 
		que.push(s);
		res++;
	}
	printf("%d\n",res);
	
	return 0;
}