HDU2842之斐波那契亚数列变形,动态规划
2014-07-18 15:25
239 查看
1.原题展示:
一根棒子上有n个环(n<=10^9) 第一个环可以随意取下或者放上 如果前k个环都不在棒子上,且第k+1个环在棒子上,则你可以取下或放上第k+2个环 给出n,求最少需要多少步可以取完棒子上的环?
2.思路分析:
如果要把n个环全部拿完,那么我们必须先拿完前n-2个环(只有这样才能拿走第n个环),剩下第n-1个环未拿走。当拿走前n-2个环所花的步骤数目为f(n-2)加上最后一个环,那么所花步数为f(n-2)+1步.对于第n-1个球,如果要拿走它,必须补上前n-2个球,放进去n-2个球所花步数为f(n-2)步。此时棒上共有n-1个环,要全部拿走,则所需步数为f(n-1)步。到这里我们就可以得到递推公式了:f(n)=f(n-2)+1+f(n-2)+f(n-1)=2*f(n-2)+f(n-1)+1.
对于这种递推公式,我们考虑矩阵的快速幂求法,首先我们需要构造出几个基本矩阵。
矩阵init:
1 2 1
1 0 0
0 0 1
矩阵r:(构造有技巧,每次乘init后第一列都会按照f(k-1),f(k-2),1的格式排列,因而保证了递推关系的成立)
2 0 0
1 0 0
1 0 0
所以f(n)为矩阵init^n-2*r的第一个数字。
3.代码如下:
一根棒子上有n个环(n<=10^9) 第一个环可以随意取下或者放上 如果前k个环都不在棒子上,且第k+1个环在棒子上,则你可以取下或放上第k+2个环 给出n,求最少需要多少步可以取完棒子上的环?
2.思路分析:
如果要把n个环全部拿完,那么我们必须先拿完前n-2个环(只有这样才能拿走第n个环),剩下第n-1个环未拿走。当拿走前n-2个环所花的步骤数目为f(n-2)加上最后一个环,那么所花步数为f(n-2)+1步.对于第n-1个球,如果要拿走它,必须补上前n-2个球,放进去n-2个球所花步数为f(n-2)步。此时棒上共有n-1个环,要全部拿走,则所需步数为f(n-1)步。到这里我们就可以得到递推公式了:f(n)=f(n-2)+1+f(n-2)+f(n-1)=2*f(n-2)+f(n-1)+1.
对于这种递推公式,我们考虑矩阵的快速幂求法,首先我们需要构造出几个基本矩阵。
矩阵init:
1 2 1
1 0 0
0 0 1
矩阵r:(构造有技巧,每次乘init后第一列都会按照f(k-1),f(k-2),1的格式排列,因而保证了递推关系的成立)
2 0 0
1 0 0
1 0 0
所以f(n)为矩阵init^n-2*r的第一个数字。
3.代码如下:
#include<stdio.h> #include<stdlib.h> #include<string.h> #define size 3 #define mod 200907 struct Mat { long long num[size][size]; }; Mat init,r;//定义全局变量; void InitMat()//初始化全局变量函数 { int i,j; for (i=0;i<size;i++) for (j=0;j<size;j++) r.num[i][j] = init.num[i][j] = 0; r.num[1][0] = r.num[2][0] = init.num[0][0]=init.num[0][2]=init.num[1][0]=init.num[2][2]=1; r.num[0][0] = init.num[0][1]= 2; } Mat mul(Mat m,Mat r)//矩阵相乘 { Mat c; memset(c.num,0,sizeof(c.num)); for (int i=0;i<size;i++) { for (int j=0;j<size;j++) { c.num[i][j] = 0; for(int k=0;k<size;k++) c.num[i][j]+=(m.num[i][k]*r.num[k][j])%mod; c.num[i][j]%=mod; }//矩阵相乘并赋给ans } return c;//返回最后的值 } Mat pow(Mat m,int k)//矩阵的乘方函数 { Mat ans; memset(ans.num,0,sizeof(ans.num));//首先置为0 for(int i=0;i<size;i++) for(int j=0;j<size;j++) if(i==j) ans.num[i][j]=1;//置为单位矩阵 while(k) { if(k&1) ans = mul(ans,m);//开始矩阵的乘方 k >>= 1; m = mul(m,m); } return ans;//返回所求矩阵 } int main() { int n; InitMat(); while (scanf("%d",&n)!=EOF) { if(n==1) printf("1\n"); else if(n==2) printf("2\n"); else { Mat multi=pow(init,n-2); Mat t=mul(multi,r); printf("%lld\n",t.num[0][0]); } } return 0; }
相关文章推荐
- 斐波那契数列的实现(简单递归和动态规划)
- [ACM_动态规划] hdu 1176 免费馅饼 [变形数塔问题]
- hdu 1250 高精度+类似斐波那契数列
- HDU 1588 斐波那契数列数列变形和矩阵连乘
- hdu 4549 M斐波那契数列
- 递归思想斐波那契数列变形
- 斐波那契数列的变形
- hdu 1176 免费馅饼(动态规划 数字三角形问题变形)
- G - 免费馅饼 HDU 1176 (动态规划---数塔的变形 )
- 斐波那契数列的变形(大众点评2015校园招聘测试岗的第一道编程题)
- 斐波那契数列的变形---跳台阶及矩形覆盖
- HDU 5451 广义斐波那契数列
- 斐波那契数列(Fibonacci)(递归,非递归)(动态规划,自顶向下,自底向上)
- HDU -2018 母牛的故事&&斐波那契兔子数列(函数递归)
- 斐波那契数列及变形题
- HDU 1176 免费馅饼 动态规划 数塔变形
- HDU Problem J [ 一只小蜜蜂 ]——基础dp斐波那契数列
- 一个斐波那契数列题 HDU 2041
- hdu 1069 Monkey and Banana 动态规划(最长递增子序列变形)
- hdu 1574 RP问题 动态规划,01背包的变形