AcWing 1303. 斐波那契前 n 项和 快速幂+矩阵乘法

AcWing 1303. 斐波那契前 n 项和

大家都知道 Fibonacci 数列吧,f1=1,f2=1,f3=2,f4=3,…,fn=fn−1+fn−2。

现在问题很简单,输入 n 和 m,求 fn 的前 n 项和 Snmodm。

输入格式
共一行,包含两个整数 n 和 m。

输出格式
输出前 n 项和 Snmodm 的值。

数据范围
1≤n≤2000000000,
1≤m≤1000000010
输入样例:
5 1000
输出样例:
12

这道题我本来想用简单的暴力解决问题,但是我发现测试样例很大,我知道暴力肯定过不去,然后看y总的视频,才了解到一个交线性代数的矩阵相乘算法,我现在还在大一,我们还没开始线性代数的学习,所以我理解起来会有点很吃力,然后我就看b站的视频,但是毫无效果,然后我就对y总的代码进行了模拟,才知道了矩阵相乘的规律。

其实y总的推理古城也很复杂,这道题注定不会很简单的去解决。
会线性代数的看看这个大佬的题解

所以最主要的思想是:
矩阵相乘和快速幂。

因为最后的结果是矩阵
f i [ ] = ( f   n   , f   n − 1   , S   n + 1   ) fi[ ]=(f~n~, f~n-1~ , S~n+1~) fi[]=(f n ,f n1 ,S n+1 )

然后我们的代码应该是
f   0   ∗ a 的 n − 1 次 方 f~0~ * a的n-1次方 f 0 an1

最后的代码如下:

#include
#include
#include

using namespace std;
typedef long long LL;

const int N=3;
int n,mod;
int a[N][N]=
{
     
    {
     0,1,0},
    {
     1,1,1},
    {
     0,0,1}
};
int fi[N]={
     1,1,1};

void mul(int t[],int b[],int c[][N])
{
     
    int temp[N]={
     0};
    for(int i=0;i;i++)
    for(int j=0;j;j++)
    temp[i]=(temp[i]+(LL)b[j]*c[j][i])%mod;
    memcpy(t,temp,sizeof temp);
}
void mul(int t[][N],int b[][N],int c[][N])
{
     
    int temp[N][N]={
     0};
    for(int i=0;i;i++)
    for(int j=0;j;j++)
    for(int k=0;k;k++)
    temp[i][j]=(LL)(temp[i][j]+(LL)b[i][k]*c[k][j])%mod;
    memcpy(t,temp,sizeof temp);
}
int main(void)
{
     
    cin>>n>>mod;
    n--;
    while(n)
    {
     
        if(n&1) mul(fi,fi,a);
        mul(a,a,a);
        n>>=1;
    }
    cout<;
}

你可能感兴趣的:(蓝桥杯,A/B组训练(省赛),数论,蓝桥杯,A/B组训练)