PTA一步两步

一、题目描述

 

 二、解题思路

  这个题用常规的dp是行不通的,应为数据量太大了。那么应该怎么优化呢。

  答案是采用矩阵优化

  我们构造一个这样的矩阵,然后乘以以F1、F2构造得2*1的矩阵

  

 

   为了发现规律,我们再乘一次

  

 

 

   我们发现每一次左乘一个我们构造得这样的矩阵,我们都会得到下一个数列。分析下标关系可知,我们只需要左边的矩阵左乘n-2次,即可以得到Fn。因为是左乘n-2次,我们可以用快速幂进行优化,类似于以前求指数的形式。

 

 

三、代码实现

 1 #include "bits/stdc++.h"
 2 #define PII pair<int,int>
 3 #define rep(i,z,n) for(int i = z;i <= n; i++)
 4 #define per(i,n,z) for(int i = n;i >= z; i--)
 5 #define ll long long
 6 #define db double
 7 #define vi vector<int>
 8 #define debug(x) cerr << "!!!" << x << endl;
 9 using namespace std;
10 //从某个串中把某个子串替换成另一个子串
11 string& replace_all(string& src, const string& old_value, const string& new_value) {
12     // 每次重新定位起始位置,防止上轮替换后的字符串形成新的old_value
13     for (string::size_type pos(0); pos != string::npos; pos += new_value.length()) {
14         if ((pos = src.find(old_value, pos)) != string::npos) {
15             src.replace(pos, old_value.length(), new_value);
16         }
17         else break;
18     }
19     return src;
20 }
21 inline ll read()
22 {
23     ll s,r;
24     r = 1;
25     s = 0;
26     char ch = getchar();
27     while(ch < '0' || ch > '9'){
28         if(ch == '-')
29             r = -1;
30         ch = getchar();
31     }
32     while(ch >= '0' && ch <= '9'){
33         s = (s << 1) + (s << 3) + (ch ^ 48);
34         ch = getchar();
35     }
36     return s * r;
37 }
38 inline void write(ll x)
39 {
40     if(x < 0) putchar('-'),x = -x;
41     if(x > 9) write(x / 10);
42     putchar(x % 10 + '0');
43 }
44 const int N = 2;
45 const int mod = 1e9+7;
46 void Multi_Matrix(ll a[][N + 1],ll b[][N + 1],int prow,int pcol,int lrow,int lcol)
47 {
48     //pcol是前面矩阵的列
49     //lrow是后面矩阵的行
50     if(pcol != lrow){
51         cout << "error" << endl;
52         return;
53     }
54     ll c[N + 1][N + 1];
55     memset(c,0,sizeof(c));
56     for(int i = 1;i <= prow;i++)
57         for(int j = 1;j <= lcol;j++)
58             for(int k = 1;k <= pcol;k++)
59                 c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % mod;
60 
61     //相乘的结果赋值给原来的矩阵
62     for(int i = 1;i <= prow;i++)
63         for(int j = 1;j <= lcol;j++)
64             a[i][j] = c[i][j];
65 }
66 //矩阵快速幂
67 void Qpow_Matrix(ll a[N + 1][N + 1],ll n)
68 {
69     ll res[N + 1][N + 1];
70     for(int i = 1;i <= N;i++)
71         for(int j = 1;j <= N;j++)
72             res[i][j] = 1;
73     while(n){
74         if(n & 1)
75             Multi_Matrix(res,a,N,N,N,N);
76         Multi_Matrix(a,a,N,N,N,N);
77         n >>= 1;
78     }
79     //把相乘后的答案还给原矩阵
80     for(int i = 1;i <= N;i++)
81         for(int j = 1;j <= N;j++)
82             a[i][j] = res[i][j];
83 }
84 int main()
85 {
86     ll n;
87     n = read();
88     if(n == 1 || n == 2){
89         cout << 1 << endl;
90         return 0;
91     }
92     ll a[N + 1][N + 1];
93     a[1][1] = 1;a[1][2] = 1;
94     a[2][1] = 1;a[2][2] = 0;
95     Qpow_Matrix(a,n - 2);
96     cout << a[1][1] << endl;
97     return 0;
98 }
posted @ 2022-03-23 22:02  scannerkk  阅读(65)  评论(0)    收藏  举报