【打表计划】【小澳的坐标系】 矩阵快速幂

来源:互联网 发布:如何做好酒店网络销售 编辑:程序博客网 时间:2024/05/21 10:30

【打表计划】

题目描述

CYR 想打 n个表,他一次可以打一个、两个、三个或四个表,求他打 n 个表的方案总数。

输入格式

一行一个整数 n,表示 CYR 想打的表的数量。

输出格式

一行一个整数,表示 CYR 打表的方案数,答案对2769433 取模。

测试样例

样例输入
4

样例输出
8

数据范围与提示

对于 30% 的数据,n≤5;
对于 50% 的数据,n≤10 ^ 5​​;
对于 80% 的数据,n≤10 ^ 9;
对于 100% 的数据,n≤10 ^ 16​​。

我本来以为这道题是跟跳台阶一样的水题【naive】,结果是矩阵快速幂,可是我矩乘和快速幂都不会啊【滑稽*n】

//代码主要是抄Menci和Rachel的qnq #include <cstdio>#include <cstring>#include <iostream>using namespace std;const int MOD = 2769433;long long n;struct Matrix {    long long a[4][4];    Matrix ()    {        memset(a, 0, sizeof(a));    }};Matrix operator* (const Matrix &a, const Matrix &b){    Matrix res;    for (int i = 0; i < 4; i++)    {        for (int j = 0; j < 4; j++)        {            for (int k = 0; k < 4; k++)            {                res.a[i][j] = (res.a[i][j] % MOD + (a.a[i][k] % MOD * b.a[k][j] % MOD) % MOD) % MOD;            }        }    }    return res;}Matrix pow(Matrix a, long long n){    Matrix res;    if (n == 0)    {        res.a[0][0] = res.a[1][1] = res.a[2][2] = res.a[3][3] = 1; //单位矩阵 相当于1,也就是每个数乘它都得到自己本身         return res;    }    else if (n % 2 == 1)    {        return pow(a * a, n / 2) * a;    }    else    {        return pow(a * a, n / 2);    }}int main(){    scanf("%lld", &n);    if (n == 0)    {        printf("1\n");    }    else if (n == 1)    {        printf("1\n");    }    else if (n == 2)    {        printf("2\n");    }    else if (n == 3)    {        printf("4\n");    }    else if (n == 4)    {        printf("8\n");    }    else    {        Matrix t, s;        s.a[0][0] = 1, s.a[1][0] = 2, s.a[2][0] = 4, s.a[3][0] = 8;        t.a[0][0] = 0, t.a[0][1] = 1, t.a[0][2] = 0, t.a[0][3] = 0;        t.a[1][0] = 0, t.a[1][1] = 0, t.a[1][2] = 1, t.a[1][3] = 0;        t.a[2][0] = 0, t.a[2][1] = 0, t.a[2][2] = 0, t.a[2][3] = 1;        t.a[3][0] = 1, t.a[3][1] = 1, t.a[3][2] = 1, t.a[3][3] = 1;        s = pow(t, n - 4) * s;        long long ans = s.a[3][0];        printf("%lld\n", ans);    }}

我一开始想的是开两个结构体,因为有两个不同形状的矩阵嘛【滑稽】,但其实开一个结构体就行了,就是大的那个矩阵的形状,小的也用那个,不足的就直接补零了,方便了好多。

【小澳的坐标系】

题目描述

小澳的梦境中出现了一个平面直角坐标系,自原点,向四方无限延伸。

小澳在坐标系的原点,他可以向上、向左或者向右走。他可以走 n 步,但不能经过相同的点。

小澳想知道他有多少种走法。

输入格式

输入文件仅第一行一个正整数 n ,表示小澳可以走的步数。

输出格式

输出文件共一行,输出一个正整数,表示答案(对10 ^ 9 + 7取模)。

测试样例

样例输入 1
2

样例输出 1
7

样例输入 2
3

样例输出 2
17

数据范围与提示

测试点编号
n
1−2 n≤10
3−4 n≤100
5−6 n≤1000
7−8 n≤10 ^ 6​​
9−10 n≤10 ^ 9

//代码还是主要抄Menci和Rachel的qnq 我已经是个废鱼了qnq #include <cstdio>#include <iostream>#include <algorithm>#include <cstring>using namespace std;const int MOD = 1e9 + 7;struct Matrix {    long long a[2][2];    Matrix()    {        memset(a, 0, sizeof(a));    }};Matrix operator*(const Matrix &a, const Matrix &b){    Matrix res;    for (int i = 0; i < 2; i++)    {        for (int j = 0; j < 2; j++)        {            for (int k = 0; k < 2; k++)            {                res.a[i][j] = (res.a[i][j] % MOD + (a.a[i][k] % MOD * b.a[k][j] % MOD) % MOD) % MOD;            }        }    }    return res;}Matrix pow(Matrix a, long long n){    Matrix res;    if (n == 0)    {        res.a[0][0] = res.a[1][1] = 1;        return res;    }    else    {        if (n % 2 == 1)        {            return pow(a * a, n / 2) * a;        }        else        {            return pow(a * a, n / 2);        }    }}int main(){    //freopen("coordinate.in", "r", stdin);    //freopen("coordinate.out", "w", stdout);     long long n;    scanf("%lld", &n);    if (n == 1) printf("3\n");    else if (n == 2) printf("7\n");    else    {        Matrix t, s;        t.a[0][0] = 3; t.a[1][0] = 7;        s.a[0][0] = 0; s.a[0][1] = 1;        s.a[1][0] = 1; s.a[1][1] = 2;        t = pow(s, n - 1) * t; //不懂         long long ans = t.a[0][0] % MOD; //不懂         printf("%lld\n", ans);    }    return 0;}

两道题我都是照着题解写的【辣鸡】,转移矩阵自己没推,不过自己凑一个只要满足要求就行。就像小澳的坐标系,题解的转移矩阵是【1,1】【2,1】,i在上,i - 1在下,而Rachel的是【0,1】【1,2】,是i - 1再上,i在下,都能A。
当n=0时的单位矩阵是我没有想到的,就是找一个矩阵让它乘自己自己不变。
还有转移矩阵一般都是方的

pow还可以写成

orz pow(orz a, int u){    orz res;    res.a[0][0] = res.a[1][1] = 1;    for (; u; u >>= 1, a = a * a) if (u & 1) res = res * a;    return res;}

//代码大都不是我自己写的,侵删

0 0
原创粉丝点击