• noip模拟赛 数列


    题目描述

    a[1]=a[2]=a[3]=1

    a[x]=a[x-3]+a[x-1] (x>3)

    求a数列的第n项对1000000007(10^9+7)取余的值。

    输入输出格式

    输入格式:

    第一行一个整数T,表示询问个数。

    以下T行,每行一个正整数n。

    输出格式:

    每行输出一个非负整数表示答案。

    输入输出样例

    输入样例#1:
    3
    6
    8
    10
    输出样例#1:
    4
    9
    19

    说明

    对于30%的数据 n<=100;

    对于60%的数据 n<=2*10^7;

    对于100%的数据 T<=100,n<=2*10^9;

    分析:dfs有30分,记忆化搜索有60分,剩下40分要怎么得到呢?求数列第n项可以用矩阵来优化.每一个f(i) (i > 3)都能表示成a*f(1) + b*f(2) + c*f(3),利用矩阵相乘的定义,构造矩阵,由于不方便打出来,可以在纸上画一下:

    f(n)         1  0  1       f(n-1)

    f(n-1)   =   1  0  0   *   f(n-2)

    f(n-2)    0  1  0       f(n-3)

    事实上我们只需要第二个矩阵的n-3次方就好了,结果就是所得矩阵第一行的三个数之和.

    #include <cstdio>
    #include <iostream>
    #include <cstring>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    const int mod = 1000000007;
    
    long long T,n,op[4][4],a[4][4],b[4][4];
    long long temp[4][4],ans;
    
    void init()
    {
        op[1][1] = 1;
        op[1][2] = 0;
        op[1][3] = 1;
        op[2][1] = 1;
        op[2][2] = 0;
        op[2][3] = 0;
        op[3][1] = 0;
        op[3][2] = 1;
        op[3][3] = 0;
    }
    
    void mul1()
    {
        memset(temp, 0, sizeof(temp));
        for (int k = 1; k <= 3; k++)
        for (int i = 1; i <= 3; i++)
            if (a[i][k])
            for (int j = 1; j <= 3; j++)
            temp[i][j] += a[i][k] * b[k][j];
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (temp[i][j] < mod)
                    a[i][j] = temp[i][j];
                else
                    a[i][j] = temp[i][j] % mod;
    }
    
    void mul2()
    {
        memset(temp, 0, sizeof(temp));
        for (int k = 1; k <= 3; k++)
            for (int i = 1; i <= 3; i++)
                if (b[i][k])
                    for (int j = 1; j <= 3; j++)
                        temp[i][j] += b[i][k] * b[k][j];
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                if (temp[i][j] < mod)
                    b[i][j] = temp[i][j];
                else
                    b[i][j] = temp[i][j] % mod;
    }
    
    int main()
    {
        scanf("%lld", &T);
        init();
        while (T--)
        {
            memset(a, 0, sizeof(a));
            memset(b, 0, sizeof(b));
            scanf("%lld", &n);
            if (n <= 3)
                printf("1
    ");
            else
            {
                n -= 3;
                a[1][1] = a[2][2] = a[3][3] = 1;
                memcpy(b, op, sizeof(b));
                while (n)
                {
                    if (n & 1)
                        mul1();
                    n >>= 1;
                    mul2();
                }
                ans = (a[1][1] + a[1][2] + a[1][3]) % mod;
                printf("%lld
    ", ans);
            }
        }
        
    
        return 0;
    }
  • 相关阅读:
    Docker 笔记
    Win10 Docker 安装使用
    golang struct转map
    Golang 中错误与异常需要重新认识
    Golang 中三种读取文件发放性能对比
    GoLang中如何使用多参数属性传参
    GoLang中flag标签使用
    Windows本地搭建Edusoho环境
    edusoho上传视频弹出abort之解决方案
    XAMPP启动mysql遇到的问题
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7537676.html
Copyright © 2020-2023  润新知