dp超时的另外一种优化,找规律(四塔问题)
四塔问题
“汉诺塔”,是一个众所周知的古老游戏。现在我们把问题稍微改变一下:如果一共有4根柱子,
而不是3根,那么至少需要移动盘子多少次,才能把所有的盘子从第1根柱子移动到第4根柱子上呢?
为了编程方便,您只需要输出这个结果mod 10000的值。
输入
一个正整数n。(0<n<=50000)
输出
一个正整数,表示把n个盘子从第1根柱子移动到第4根柱子需要的最少移动次数mod 10000的值。
样例输入
15
样例输出
129
这道题一看到题,就是dp
那么
按照三塔问题的思路设dp(i)表示把i个盘子从一个柱子通过其他两个柱子移动到第四根柱子,在移动的时候我们发现,这还要用到3塔问题,那么我们应该预处理一下三塔问题
这以我们用f(i)表示把前i个盘子从一根柱子通过其他一根柱子移动到第三根柱子。
dp(i)=2(dp(i-1-k)*f(k))+1(0<=k<i)
由于最后是求出余数的最大值,那么用这个方程的话,就不满足同余定理,只能有高精度来算。高精度的话这道题超时很严重。
这时候打出前100的数据,仔细看可以发现 两个数之间的差值为2 2 4 4 4 8 8 8 8 16 16 16 16 16……找出这个的话,问题很easy了。
#include<cstdio> #include<algorithm> using namespace std; const int mod = 10000; const int Max_N = 50002; int dp[Max_N]; int main() { int i , j = 0, k = 2, t = 2; dp[1] = 1; for(i = 2;i <= Max_N-2;i++){ j++; dp[i] = (dp[i - 1] + t) % mod; if(j == k){ j = 0; k++; t *= 2; t %= mod; } } int n; while(scanf("%d",&n)!=EOF) printf("%d",dp[n]); return 0; }
我们发现当一个操作性很强的dp题目出现时,我们可以通过找规律优化
夫君子之行,
静以修身,俭以养德;
非澹泊无以明志,
非宁静无以致远。
夫学须静也,才须学也;
非学无以广才,非志无以成学。
慆慢则不能励精,
险躁则不能冶性。
年与时驰,意与日去,
遂成枯落,多不接世。
悲守穷庐,将复何及!