• AcWing1303. 斐波那契前 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
    

    矩阵快速幂板子题。设前n项和为(S_n),有(S_n - S_{n - 1} = f_n = f_{n - 1} + f_{n - 2} = S_{n - 1} - S_{n - 2} + S_{n - 2} - S_{n - 3}),得到(S_n = 2 imes S_{n - 1} - S_{n - 3}),显然转移矩阵为:

    2 0 -1

    1 0 0

    0 1 0

    搞一搞就行了

    注意转移矩阵有减法,在进行矩阵乘法的时候注意多加几个mod防爆!!!

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    #define int long long
    #define N 3
    struct Mat
    {
        LL m[101][101];
        void print() {
        	for(int i = 1; i <= N; i++) {
        		for(int j = 1; j <= N; j++) {
        			cout << m[i][j] << " ";
        		}
        		cout << endl;
        	}
        }
    };//存储结构体
    Mat a,e; //a是输入的矩阵,e是输出的矩阵
    Mat Mul(Mat x,Mat y, long long mod)
    {
        Mat c;
        for(int i=1;i<=N;++i){
            for(int j=1;j<=N;++j){
                c.m[i][j] = 0;
            }
        }
        for(int i=1;i<=N;++i){
            for(int j=1;j<=N;++j){
                for(int k=1;k<=N;++k){
                    c.m[i][j] = (c.m[i][j]%mod + x.m[i][k]%mod*y.m[k][j]%mod + mod + mod) % mod;//注意有减法!!得多加mod 要不然就爆了
                }
            }
        }
        return c;
    }
    Mat pow(Mat x,LL y, long long mod)//矩阵快速幂
    {
    	for(int i = 1; i <= N; i++) {
    		for(int j = 1; j <= N; j++) {
    			e.m[i][j] = 0;
    		}
    	}
    	for(int i = 1; i <= N; i++) {
    		e.m[i][i] = 1;
    	}
        Mat ans = e;
        while(y){
            if(y&1) ans = Mul(ans,x,mod);
            x = Mul(x,x,mod);
            y>>=1;
        }
        return ans;
    }
    long long n, m;
    signed main() {
    	cin >> n >> m;
    	Mat base;
    	for(int i = 1; i <= 3; i++) {
    		for(int j = 1; j <= 3; j++) {
    			base.m[i][j] = 0;
    		}
    	}
    	base.m[1][1] = 2, base.m[1][3] = -1, base.m[2][1] = 1, base.m[3][2] = 1;
    	//base.print();
    	Mat S;
    	for(int i = 1; i <= 3; i++) {
    		for(int j = 1; j <= 3; j++) {
    			S.m[i][j] = 0;
    		}
    	}
    	S.m[1][1] = 4, S.m[2][1] = 2, S.m[3][1] = 1;
    	if(n == 1) cout << 1;
    	else if(n == 2) cout << 2;
    	else if(n == 3) cout << 4;
    	else {
    		Mat tmp = pow(base, n - 3, m);
    		Mat ans = Mul(tmp, S, m);
    		cout << ans.m[1][1];
    	}
    	return 0;
    }
    
  • 相关阅读:
    mongodb的常用操作(二)
    mongodb的常用操作
    OpenBSD内核之引导PBR
    OpenBSD内核之引导MBR
    OpenBSD之开篇
    “索引”、大数据的思考
    flume坑之channel.transactionCapacity和HdfsSink.batchSize
    cocos2d-x的CCAffineTransform相关变换实现原理
    MySQL JDBC/MyBatis Stream方式读取SELECT超大结果集
    “全服单世界”的终极目标即“虚拟世界”
  • 原文地址:https://www.cnblogs.com/lipoicyclic/p/14994631.html
Copyright © 2020-2023  润新知