牛客-kotori和糖果(哈斯圖嗎?)

題意:開始時有n堆糖,每堆開始時有1個把這些糖果聚在一堆。但她每次只能把兩堆糖果合併成一堆。

已知把兩堆數量爲a和b的糖果聚在一堆的代價是|a-b|。

kotori想知道,她把這n塊糖果聚在一堆的最小代價是多少?
題目鏈接

one:

for(int i=1;i<=1e18+10;i++)
{
		m[i] = m[i/2]+m[i-i/2] +i%2;
}

problem:複雜度過高,達到了1e18

two:

可以想到,可以使用遞歸來優化
(坑點1:n=0)

ll init(ll n)
{
	if(n==1||n==0)   return 0;
	if(n&1) return m[n] = init(n/2) + init(n/2+1)+1;
	else return m[n] = init(n/2)*2;
}
void main():
{
	init(1e18);                 //初始化
}
//坑點1:n=0

problem:從1到1e18不能都初始化,而且有很多重複的
搜索樹

three:

ll init(ll n)
{
	if(m[n]) return m[n];
	if(n==1||n==0)   return 0;
	if(n&1) return m[n] = init(n/2) + init(n/2+1)+1;
	else return m[n] = init(n/2)*2;                   //這裏可以減少遞歸
}

four

1e5以下碰撞次數太多,這樣可以減小碰撞

if(n&1) return cal(n/2) + cal(n/2+1)+1;
else return cal(n/2)*2;
這個最好不要合併,不合並可以減少遞歸次數

void init()
{
	for(int i=3;i<=100000;i++) 
		{
			m[i] = m[i/2]+m[i-i/2]+i%2;
		}
]

ll cal(ll n)
{
	if(n<=maxn) return m[n];
	else
	{
		if(n&1) return cal(n/2) + cal(n/2+1)+1;
		else return cal(n/2)*2;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章