題意:開始時有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;
}
}