[abmfy]新宝岛

· · 个人记录

[abmfy]新宝岛

题意简述

初始状态为1,进行n次转移,问最终状态为1的方案数对 10^9+7 取模的结果。下面给出转移方式:

ans_i 表示最终状态为 i 的方案数,初始数组 B=\begin{Bmatrix} 1 & 0 & 0 \end{Bmatrix},显然有

ans_{i}=\sum_{j=1}^3 A^n_{i,j} \cdot B_{j}.

即答案为

ans_1=\sum_{j=1}^3 A^n_{1,j} \cdot B_{j}.

矩阵乘幂简介:

对于时间,显然时间复杂度随着变量的增大单调递增,因此当 n 取最大值 10^9 时,时间复杂度最大,即 \log_2 10^9 \approx 30=3 \times 10<4 \times 10^8,所以不会超时。

对于空间,显然空间复杂度与变量的增大无关,所以不会超空间。

代码实现

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll n,a[3][3] = {{0,1,1},{1,0,0},{1,1,1}},b[3] = {1,0,0},dp[3],c[3][3],res[3][3];
int main(){
    memset(res,0,sizeof(res));
    scanf("%lld",&n);
    for(ll i = 0;i <= 2;i++)res[i][i] = 1;
    while(n){
        if(n % 2 == 1){
            memset(c,0,sizeof(c));
            for(ll i = 0;i <= 2;i++)for(ll j = 0;j <= 2;j++)for(ll k = 0;k <= 2;k++)c[i][j] = (c[i][j] + res[i][k] * a[k][j] % 1000000007) % 1000000007;
            for(ll i = 0;i <= 2;i++)for(ll j = 0;j <= 2;j++)res[i][j] = c[i][j];
        }
        memset(c,0,sizeof(c));
        for(ll i = 0;i <= 2;i++)for(ll j = 0;j <= 2;j++)for(ll k = 0;k <= 2;k++)c[i][j] = (c[i][j] + a[i][k] * a[k][j] % 1000000007) % 1000000007;
        for(ll i = 0;i <= 2;i++)for(ll j = 0;j <= 2;j++)a[i][j] = c[i][j];
        n /= 2;
    }
    for(ll i = 0;i <= 2;i++)for(ll j = 0;j <= 2;j++)dp[i] = (dp[i] + res[i][j] * b[j] % 1000000007) % 1000000007;
    printf("%lld",dp[0]);
    return 0;
}