SDNU 1313.Chess 找规律 矩阵快速幂


1313.Chess


Description

小X有一个1*n的跳棋棋盘。今天小X要去参加比赛,他希望所有的跳棋排成他希望的队形(即在指定的格子上有棋子)来给他加油。小X只能在棋盘的第1个格或第2个格放置棋子,而其他的格子只能通过跳棋的跳跃到达。当且仅当第i格有棋子,i+1格有棋子,i+2格为空的时候,i格上的棋子能够跳到i+2格上,与此同时i+1格子上的棋子会消失。同理,当且仅当第i格有棋子,i-1格有棋子,i-2格为空的时候,i格上的棋子能够跳到i-2格上,与此同时i-1格子上的棋子会消失。

现在告诉你小X希望那些格子上需要有棋子,你的任务是求出最少需要在棋盘上放置多少个棋子才能做到。

由于这个答案可能过大,为了简化问题,你只需要输出最终答案模268435456的余数。


Input

第一行2个整数:n,m。n表示棋盘的大小,m表示希望放置棋子的格子个数。2

接下来m行,每行一个整数a,表示在第a个格子上需要放置一枚棋子。


Output

一个整数,最少需要放置的棋子数量 mod 268435456。


Sample Input

4 2
3
4

Sample Output

5


    题目中文不必解释什么,数字很大,所以先笔算在纸上找一下规律出来,多写几个情况之后就会发现这个数所对应的情况就是斐波那契数列,而数很大的斐波那契就很容易想到用矩阵快速幂来做了,没什么多说的了,下面AC代码:

#include
#include
#include
#include
using namespace std;
const long long mod=268435456;

struct matrix
{
     long long mat[2][2];
};

matrix multiply(matrix a,matrix b)
{
     int i,j,k;
     matrix t;
     for(i=0;i<2;i++)
     {
          for(j=0;j<2;j++)
          {
               t.mat[i][j]=0;
               for(k=0;k<2;k++)
               {
                    t.mat[i][j]=(t.mat[i][j]+a.mat[i][k]*b.mat[k][j])%mod;
               }
          }
     }
     return t;
}

long long fibonacci(long long a)
{
     matrix x,y;
     x.mat[0][0]=x.mat[0][1]=x.mat[1][0]=1;
     x.mat[1][1]=0;
     y.mat[0][0]=y.mat[1][1]=1;
     y.mat[0][1]=y.mat[1][0]=0;
     while(a)
     {
          if(a&1)
          {
               y=multiply(y,x);
          }
          x=multiply(x,x);
          a=a>>1;
     }
     return y.mat[0][1];
}

int main()
{
     int n,m;
     int i;
     long long p;
     long long ans;
     while(scanf("%d%d",&n,&m)!=EOF)
     {
          ans=0;
          for(i=0;i

你可能感兴趣的:(SDNU)