赛后题解——问题 G: 强(矩阵快速幂)

注释:能打表找规律的绝对不推导了,省时,身有体会!!!

问题 G: 强
题目描述

Lh:粉兔你教我一下抽屉原理吧
Clz:就是给你一个长度为 n \small n n的序列,每个数只能取 0 , 1 , 2 \small 0,1,2 0,1,2那你连续取三个数必然有两个相等……
Lh:等等你梭啥,再说一遍
Clz:……emmm 当我没说
Marser:就是一个序列,对于每一个连续三元组都要满足其中至少有两个相等
现在粉兔问你:有多少个长度为 n \small n n的序列满足粉兔的要求?请对19260817取模。

输入

一行一个正整数 n \small n n 3 ≤ n ≤ 1 0 18 \small 3≤n≤10^{18} 3n1018)。

输出

一行一个整数,含义如题。

样例输入

4

样例输出

51

提示

51 种序列如下:
[0,0,0,0],[0,0,0,1],[0,0,0,2],[0,0,1,0],[0,0,1,1],[0,0,2,0],[0,0,2,2],[0,1,0,0],[0,1,0,1],[0,1,1,0],[0,1,1,1],[0,1,1,2],[0,2,0,0],[0,2,0,2],[0,2,2,0],[0,2,2,1],[0,2,2,2],[1,0,0,0],[1,0,0,1],[1,0,0,2],[1,0,1,0],[1,0,1,1],[1,1,0,0],[1,1,0,1],[1,1,1,0],[1,1,1,1],[1,1,1,2],[1,1,2,1],[1,1,2,2],[1,2,1,1],[1,2,1,2],[1,2,2,0],[1,2,2,1],[1,2,2,2],[2,0,0,0],[2,0,0,1],[2,0,0,2],[2,0,2,0],[2,0,2,2],[2,1,1,0],[2,1,1,1],[2,1,1,2],[2,1,2,1],[2,1,2,2],[2,2,0,0],[2,2,0,2],[2,2,1,1],[2,2,1,2],[2,2,2,0],[2,2,2,1],[2,2,2,2]。

解决思路:直接暴力打表数学归纳法,然后矩阵快速幂加速。
上图!!!
赛后题解——问题 G: 强(矩阵快速幂)_第1张图片

结论: {   f ( 3 ) = 21   f ( 4 ) = 51   f ( n ) = 2 f ( n − 1 ) + f ( n − 2 ) \small \begin{cases} \ f(3)=21\\ \ f(4)=51\\ \ f(n)=2f(n-1)+f(n-2)\\ \end{cases}  f(3)=21 f(4)=51 f(n)=2f(n1)+f(n2)
构造矩阵:
赛后题解——问题 G: 强(矩阵快速幂)_第2张图片

//优化
#pragma GCC optimize(2)
//C
#include
#include
#include
#include
//C++
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//宏定义
#define N 1010
#define DoIdo main
//#define scanf scanf_s
#define it set::iterator
//定义+命名空间
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 19260817;
const ll INF = 1e18;
const int maxn = 1e6 + 10;
using namespace std;
//全局变量
const int m = 2;
struct mat {
    ll m[3][3];
}ans;
//函数区
ll max(ll a, ll b) { return a > b ? a : b; }
ll min(ll a, ll b) { return a < b ? a : b; }
mat operator*(mat a, mat b) {
    mat res;
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= m; j++) {
            ll temp = 0;
            for (int k = 1; k <= m; k++) {
                temp = (temp + a.m[i][k] * b.m[k][j]) % mod;
            }
            res.m[i][j] = temp;
        }
    }
    return res;
}
void init() {
    for (int i = 1; i <= m; i++) {
        for (int j = 1; j <= m; j++) {
            if (i == j) ans.m[i][j] = 1;
            else ans.m[i][j] = 0;
        }
    }
}
void quick_pow(mat a, ll b) {
    init();
    while (b) {
        if (b & 1) {
            ans = (ans * a);
        }
        a = (a * a);
        b >>= 1;
    }
}
//主函数
int DoIdo() {
 
    ios::sync_with_stdio(false);
    cin.tie(NULL), cout.tie(NULL);
 
    ll n;
    cin >> n;
 
    mat A, B; A.m[1][1] = 21, A.m[1][2] = 51;
    B.m[1][1] = 0, B.m[1][2] = 1;
    B.m[2][1] = 1, B.m[2][2] = 2;
 
    if (n >= 5) quick_pow(B, n - 4);
 
 
    if (n == 3) cout << 21 << endl;
    else if (n == 4) cout << 51 << endl;
    else {
        ll ans1 = ((A.m[1][1] * ans.m[1][2]) % mod + (A.m[1][2] * ans.m[2][2]) % mod) % mod;
        cout << ans1 << endl;
    }
    return 0;
}
//分割线---------------------------------QWQ
/*
 
 
 
*/

你可能感兴趣的:(数论)