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

来源:互联网 发布:澳门网络博vs88.com 编辑:程序博客网 时间:2024/05/22 07:42

【题目来源】: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);    }}
原创粉丝点击