Codevs3332 数列

来源:互联网 发布:学python看什么书 编辑:程序博客网 时间:2024/05/03 03:01
  • 题目大意:a[1]=a[2]=a[3]=1,且a[x]=a[x-3]+a[x-1] (x>3),求a数列的第n项对1000000007(10^9+7)取余的值。

  • 思路:显然,直接乘与开数组是无法通过该题的。于是,我们想到了矩阵乘法与快速幂。开一个数组a[4]={0,1,1,1},转移矩阵为{{0,0,1},{1,0,0},{0,1,1}},经过n-3次幂后再与a相乘,这样a[3]就是所求的答案。在实际编写程序时,可以记初始矩阵为所构造的矩阵,然后进行n-4次幂。边计算边取模即可。但是我写的递归版的快速幂无法通过,所以只好又写了非递归版。

  • 代码如下:

#include<iostream>#include<cstdio>#include<cstring>using namespace std;const long long martix[4][4]={                            {0,0,0,0},                            {0,0,0,1},                            {0,1,0,0},                            {0,0,1,1}                       };const long long mod=1000000007;const long long pre[4]={0,1,1,1};struct node{    long long a[4][4];};long long t,n;node calcu(node x,node y){    node tmp;    memset(tmp.a,0,sizeof(tmp.a));    for (long long i=1;i<=3;++i)      for (long long j=1;j<=3;++j)      {          for (long long k=1;k<=3;++k)            tmp.a[i][j]=(tmp.a[i][j]%mod+(long long)(x.a[i][k]*y.a[k][j]%mod))%mod;      }    return tmp;}node work()  {      node ans,cnt;    memcpy(ans.a,martix,sizeof(ans.a));    memcpy(cnt.a,martix,sizeof(cnt.a));    n-=4;    while(n>0)                                   {          if(n&1)          {              ans=calcu(ans,cnt);          }          n>>=1;          cnt=calcu(cnt,cnt);      }      long long m=0;    m=(ans.a[1][3]+ans.a[2][3]+ans.a[3][3])%mod;    printf("%lld\n",m);}void init(){    scanf("%lld",&t);    while (t--)    {        scanf("%lld",&n);        work();    }}int main(){    freopen("seq.in","r",stdin);    freopen("seq.out","w",stdout);    init();    return 0;}
0 0