兔子的排列 題解 分治 記憶化搜尋

2022-06-10 16:54:06 字數 1069 閱讀 2386

題目的意思就是乙個序列本來是0,1,2...n-1.然後要你變成p[0],p[1],p[2]...p[n-1],通過交換相鄰的兩個數每兩個相鄰的數都可以交換一次,你可以選擇交換的順序.問你有多少種交換順序?

有兩種方法,一種複雜度\(o(n^5)\) 一種複雜度\(o(n^3)\)

首先如果乙個點換了,那麼相當於切斷了兩邊,則可以兩邊單獨考慮

則要想到分治

\(dp[l][r][bg][ed]\) 代表區間l-r中開頭為bg,結尾是ed,

最不好理解的是為什麼列舉斷點時要乘 c(r-l-1,i-l)

因為這個區間總共要交換r-l次,而中間交換了1次

所以左邊和右邊總共交換次數為r-l-1次

而左邊的交換次數為i-l次

則相當於要在r-l-1次中給左邊的交換次數安排位置

有點難理解,自己可以思考下

優化到\(o(n^3)\)的方法就是直接把dp陣列變成\(dp[l][r]\)直接省去兩維

因為你劃分兩段後你用字首和算一下就能直接判斷是否可以滿足劃分

#include#define debug cout<<"i am here"<>1;

}return ans;

}void init()

}ll c(int a,int b)

ll dfs(int l,int r,int bg,int ed)else if(l==r)else

base=base*base%mod;

b=b>>1;

}return ans;

}void init()

}ll c(int a,int b)

ll dfs(int l,int r)else if(l==r)else

preb[i]-=b[i]-b[i+1];

swap(b[i],b[i+1]);

}dp[l][r]=ans;

}return dp[l][r];

}int main()

printf("%lld\n",dfs(1,n));

return 0;

}

題解 滑雪 luogu1434 記憶化搜尋

michael喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael想知道在乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 123 451617 18196...

題解 滑雪 luogu1434 記憶化搜尋

michael喜歡滑雪。這並不奇怪,因為滑雪的確很刺激。可是為了獲得速度,滑的區域必須向下傾斜,而且當你滑到坡底,你不得不再次走上坡或者等待公升降機來載你。michael想知道在乙個區域中最長的滑坡。區域由乙個二維陣列給出。陣列的每個數字代表點的高度。下面是乙個例子 123 451617 18196...

遞迴的函式 記憶化搜尋

給定乙個函式 f a,b,c 如果 a 0 或 b 0 或 c 0 返回值為 1 如果 a 20 或 b 20 或 c 20 返回值為 f 20,20,20 如果 a b 並且 b c 返回 f a,b,c 1 f a,b 1,c 1 f a,b 1,c 其它情況返回 f a 1,b,c f a 1...