您的位置:首页 > 其它

Problem of Precision(矩阵快速幂(推理))

2017-05-31 08:21 148 查看
【题目来源】https://vjudge.net/problem/HDU-2256

【题意】

题意不再解释,相必都可以看得懂。。

【思路】

起初,我能想到的是找前一项和后一项的关系,直接通过矩阵快速幂求出来,我找到的关系是:前一项的a到下一项就变成了a²+b²,而b变成了2ab,就这样想了想,写出了关系矩阵:



接下来要考虑double的事,上网查了下double怎么取余,答案是增大一定的倍数,取余,然后再除以一定的倍数,看到这里,就自动否决了、、

接下来,看了博客,发现是另外一种思路。

找到对应的关系:

假设Fn=an+bn(sqrt(6)),Fn-1=an-1+bn-1(sqrt(6))

那么Fn=(5+2(sqrt(6)))*Fn-1

所以an+bn(sqrt(6))=(5+2(sqrt(6)))*(an-1+bn-1(sqrt(6)))

整理得:

an=5an-1+12bn-1;

bn=(2an-1+5bn-1)*sqrt(6);

根据矩阵乘法,得到一个这样的矩阵关系式:



但是,最后的值还是要double的,所以好像相比我那种,只是把中间过程的double省略了,但是接着看的时候,明白了:

(an+bn(sqrt(6)))²+(an-bn(sqrt(6)))²==2an

但是呢5-2(sqrt(6))≈≈0,所以(5-2(sqrt(6)))ⁿ≈≈0;

so (an+bn(sqrt(6)))≈2an;

又因为左边取的是下限,所以2an-1。

所以结果就是2an-1。

【代码】

#include<set>
#include<map>
#include<stack>
#include<cmath>
#include<queue>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<limits.h>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int mod=1024;
const double esp=1e-5;
typedef unsigned long long ll;
typedef long long LL;
int n;
struct mat
{
int a[3][3];
}base;
mat operator*(mat s,mat t)
{
mat r;
mem(r.a,0);
for(int i=1;i<=2;i++)
for(int j=1;j<=2;j++)
for(int p=1;p<=2;p++)
{
r.a[i][j]=r.a[i][j]+s.a[i][p]*t.a[p][j];
if(r.a[i][j]>=mod)
r.a[i][j]%=mod;
}
return r;
}
void print(mat s)
{
printf("%d %d\n",s.a[1][1],s.a[1][2]);
printf("%d %d\n",s.a[2][1],s.a[2][2]);
}
void pow_mat(mat &ans)
{
mat base,temp;
mem(base.a,0);
base.a[1][1]=5;
base.a[1][2]=2;
base.a[2][1]=12;
base.a[2][2]=5;
mem(temp.a,0);
for(int i=1;i<=2;i++)
temp.a[i][i]=1;
while(n)
{
if(n&1)
temp=temp*base;
////        print(base);
base=base*base;
//        print(base);
n>>=1;
}
ans=ans*temp;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
if(n==1)
{
printf("%d\n",9);
continue;
}
n--;
mat ans;
mem(ans.a,0);
ans.a[1][1]=5;
ans.a[1][2]=2;
pow_mat(ans);
int x=(ans.a[1][1]*2-1)%mod;
printf("%d\n",x);

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: