51nod 算法马拉松18 B 非010串 矩阵快速幂

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了51nod 算法马拉松18 B 非010串 矩阵快速幂相关的知识,希望对你有一定的参考价值。

非010串

基准时间限制:1 秒 空间限制:131072 KB 分值: 80
如果一个01字符串满足不存在010这样的子串,那么称它为非010串。
求长度为n的非010串的个数。(对1e9+7取模)
 
Input
一个数n,表示长度。(n<1e15)

Output
长度为n的非010串的个数。(对1e9+7取模)

Input示例
3

Output示例
7
解释: 000 001 011 100 101 110 111

    读完题,这样的题目肯定是能找到规律所在的,要不然数据太大根本无法算。假设现在给的长度是n,答案为f(n),那么假设最后一位是0,前面有010的可能就有f(n-1)种,同样假设最后一位是1,前面有010的可能就也有f(n-1),而这样排除的话还存在着一个问题,就是最后为0的时候可能会出现前面是01而构成010,这样就加重复了。所以假设前一位为1,再减去f(n-2),当然还可能前面是11而构成110而不是010,所以还要把多减的再加回来,即再加上一个f(n-3),这样一来就可以推出一个公式,f(n)=2*f(n-1)-f(n-2)+f(n-3)。看到这个公式,数据有那么大,所以我们用矩阵快速幂来进行处理就可以快速得出结果了。

    下面是AC代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const long long mod=1000000007;

struct matrix
{
    long long a[3][3];
};

matrix cal(matrix A,matrix B)
{
     int i,j,k;
     matrix C;
     for(i=0;i<3;i++)
     {
          for(j=0;j<3;j++)
          {
               C.a[i][j]=0;
               for(k=0;k<3;k++)
               {
                    C.a[i][j]=(C.a[i][j]+(A.a[i][k]*B.a[k][j])%mod+mod)%mod;
               }
          }
     }
     return C;
}

int out(matrix A,matrix B)
{
     cout<<"s:"<<endl;
     cout<<A.a[0][0]<<" "<<A.a[0][1]<<" "<<A.a[0][2]<<endl;
     cout<<A.a[1][0]<<" "<<A.a[1][1]<<" "<<A.a[1][2]<<endl;
     cout<<A.a[2][0]<<" "<<A.a[2][1]<<" "<<A.a[2][2]<<endl;
     cout<<"base:"<<endl;
     cout<<B.a[0][0]<<" "<<B.a[0][1]<<" "<<B.a[0][2]<<endl;
     cout<<B.a[1][0]<<" "<<B.a[1][1]<<" "<<B.a[1][2]<<endl;
     cout<<B.a[2][0]<<" "<<B.a[2][1]<<" "<<B.a[2][2]<<endl;
     return 0;
}

matrix pow_mod(long long x)
{
     matrix s,base;
     base.a[0][0]=2;
     base.a[1][0]=-1;
     base.a[2][0]=1;
     base.a[0][1]=1;
     base.a[1][1]=base.a[2][1]=0;
     base.a[1][2]=1;
     base.a[0][2]=base.a[2][2]=0;
     s.a[0][0]=7;
     s.a[0][1]=4;
     s.a[0][2]=2;
     s.a[1][0]=s.a[1][1]=s.a[1][2]=0;
     s.a[2][0]=s.a[2][1]=s.a[2][2]=0;
     out(s,base);
     while(x)
     {
          if(x&1)
               s=cal(s,base);
          base=cal(base,base);
          out(s,base);
          x>>=1;
     }
     return s;
}

int main()
{
     long long n;
     long long ans;
     while(scanf("%lld",&n)!=EOF)
     {
          if(n==0)
               cout<<0<<endl;
          else if(n==1)
               cout<<2<<endl;
          else if(n==2)
               cout<<4<<endl;
          else if(n==3)
               cout<<7<<endl;
          else
          {
               matrix t=pow_mod(n-3);
               ans=t.a[0][0]%mod;
               cout<<ans<<endl;
               /*cout<<t.a[0][1]%mod<<endl;
               cout<<t.a[1][0]%mod<<endl;
               cout<<t.a[1][1]%mod<<endl;*/
          }
     }
     return 0;
}

 

以上是关于51nod 算法马拉松18 B 非010串 矩阵快速幂的主要内容,如果未能解决你的问题,请参考以下文章

51nod算法马拉松28-c

51NOD 算法马拉松15(脱欧专场) B君的游戏(博弈)

51nod算法马拉松15

51nod算法马拉松28-a

51Nod 算法马拉松21(迎新年)

随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3