最近学了矩阵快速幂,于是趁热打铁刷了一波题。。。
要加油了!
九连环 | ||||||
| ||||||
Description | ||||||
相信大家都玩过九连环的游戏 ,九连环的规则是 :
1第一个环可以在任何时候挂到柄上或者从柄上摘下
2在任何时候,你只能操作一个环
3如果前k-2个环都没有在柄上,并且第k-1个环在柄上,这时如果第k个环在柄上的话,可以把它摘下来,如果它不在柄上,可以把它挂上去
| ||||||
Input | ||||||
给定一个数n,n不大于10的8次方,你的任务是输出从柄上摘下n个环需要的最小操作次数,测试数据不超过100组。 | ||||||
Output | ||||||
输出1行,因为结果非常大,所以你需要输出结果对素数10007的余数。 | ||||||
Sample Input | ||||||
1 | ||||||
Sample Output | ||||||
1 |
如果要去掉K个环,要先去第K个再去第K-1个以此类推...
先推导出转移矩阵之后,直接套矩阵快速幂的模板
最近做的几道题,大体部分都没改,只是改了一下递推矩阵
#include<iostream>
#include<cstdio>
#include<string.h>
#define mem(a,b) memset(a,b,sizeof(a));
#define MAXN 10007
#define LL long long
using namespace std;
LL n;
struct mat
{
LL a[4][4];
};
mat mat_mul(mat x,mat y)
{
mat ans;
mem(ans.a,0);
for(LL i=0;i<3;i++)
{
for(LL j=0;j<3;j++)
{
for(LL k=0;k<3;k++)
{
ans.a[i][j]+=x.a[i][k]*y.a[k][j];
}
ans.a[i][j]%=MAXN;
}
}
return ans;
}
LL pow(LL k)
{
mat s1,s2;
mem(s2.a,0);
mem(s1.a,0);
s1.a[0][0]=2;s1.a[1][0]=1;s1.a[2][0]=1;
s2.a[0][0]=1;s2.a[0][1]=2;s2.a[0][2]=1;
s2.a[1][0]=1;s2.a[2][2]=1;
while(k)
{
if(k&1==1)
s1=mat_mul(s2,s1);
s2=mat_mul(s2,s2);
k>>=1;
}
return s1.a[0][0];
}
int main()
{
while(cin>>n)
{
if(n==1)printf("1\n");
else if(n==2)printf("2\n");
else
{
LL t=pow(n-2);
printf("%lld\n",t);
}
}
return 0;
}