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的余数。
第一行2个整数:n,m。n表示棋盘的大小,m表示希望放置棋子的格子个数。2<n<=100000,m<=n。所有的a∈[3,n],保证按非减序给出。
接下来m行,每行一个整数a,表示在第a个格子上需要放置一枚棋子。
一个整数,最少需要放置的棋子数量 mod 268435456。
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;
}