大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2。
现在问题很简单,输入 n 和 m,求 fn 的前 n 项和 Snmodm。
输入格式:
共一行,包含两个整数 n 和 m。
输出格式:
输出前 n 项和 Sn mod m 的值。
数据范围:
1≤n≤2000000000,
1≤m≤1000000010
题意:求斐波那契数列前n项和
题解:这里,n的范围太大了,直接遍历肯定超时,这里用了一个矩阵快速幂的方法。
求第n项斐波那契的值,可以用矩阵的方法,如下:求第n+1项,可以通过第n项的矩阵乘以一个A矩阵就得到了第n+1项矩阵,又因为矩阵乘法具有结合律,那么就可以先计算A的(n-1)次方,然后再和fn相乘,就得到了第n+1个斐波那契数,求A的n次方可以用一个快速幂的方法
同理求前n项和的话,只需要再在矩阵里面再加个元素即可,A矩阵再做个变换,即可得到公式
代码:
#include
using namespace std;
typedef long long ll;
const int N=3;
ll n,m;
void mul(int f[],int a[][N]){ //矩阵乘法快速幂,一维乘以二维
int temp[N]={0};
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
temp[i]=(temp[i]+(ll)f[j]*a[j][i])%m;
}
}
memcpy(f,temp,sizeof(temp));//sizeof必须是temp,如果是f那么大小就是个指针
}
void mul(int a[][N],int b[][N]){ //二维乘以二维
int temp[N][N]={0};
for(int i=0;i<N;i++){
for(int j=0;j<N;j++){
for(int k=0;k<N;k++){
temp[i][j]=(temp[i][j]+(ll)a[i][k]*b[k][j])%m;
}
}
}
memcpy(a,temp,sizeof(temp));
}
int main()
{
cin>>n>>m;
int f1[N]= {1,1,1}; //设置初始
int a[N][N]={{0,1,0},{1,1,1},{0,0,1}};//快速幂的二维数组
n--; //求n次,那么就是f1乘以a的n减一次幂
while(n){
if(n&1)mul(f1,a); //res=res*a
mul(a,a); //a=a*a;
n=n>>1;
}
cout<<f1[2]<<endl; //取第二位就是和
return 0;
}