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

本文介绍了一个关于棋盘布局的问题,通过分析问题特点,发现其与斐波那契数列之间的联系,并利用矩阵快速幂的方法高效求解。文章提供了完整的代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


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<n<=100000,m<=n。所有的a∈[3,n],保证按非减序给出。

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


Output

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


Sample Input

4 2
3
4

Sample Output

5


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

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
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<m;i++)
          {
               scanf("%lld",&p);
               //cout<<"fibonacci("<<p<<") = "<<fibonacci(p)<<endl;
               ans=(ans+fibonacci(p)%mod)%mod;
          }
          cout<<ans<<endl;
     }
     return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值