zoukankan      html  css  js  c++  java
  • 【图灵杯 F】一道简单的递推题(矩阵快速幂,乘法模板)

    Description
    存在如下递推式:
    F(n+1)=A1*F(n)+A2*F(n-1)+…+An*F(1)
    F(n+2)=A1*F(n+1)+A2*F(n)+…+An*F(2)

    求第K项的值对1000000007取模的结果
    Input
    单组测试数据

    第一行输入两个整数 n , k (1<=n<=100,n < k<=10000000000)

    第二行输入 n 个整数 F(1) F(2) … F(n)

    第三行输入 n 个整数A1 A2 … An

    Output
    输出一个整数

    Sample Input
    2 3
    1 2
    3 4
    Sample Output
    10

    【题目链接】:http://oj.acmclub.cn/problem.php?cid=1162&pid=5

    【题意】

    【题解】

    一道裸的矩阵乘法题;
    构造一个系数矩阵

    0       1       0    ...    0
    0       0       1    ...    0
    ...
    0       0       0    ...    1
    a[n]    a[n-1]  a[n-2]...   a[1]

    (这个矩阵每乘一次(f[1],f[2],f[3]…f[n])就会往后递推一个n)

    对于k>n的询问
    求这个矩阵的(k-n)次幂;
    然后把最后的矩阵的最后一行依次乘上f[1],f[2]…f[n]相加;
    就是f[k]了;

    【Number Of WA

    0

    【完整代码】

    #include <bits/stdc++.h>
    using namespace std;
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define LL long long
    #define rep1(i,a,b) for (int i = a;i <= b;i++)
    #define rep2(i,a,b) for (int i = a;i >= b;i--)
    #define mp make_pair
    #define pb push_back
    #define fi first
    #define se second
    #define ms(x,y) memset(x,y,sizeof x)
    #define Open() freopen("F:\rush.txt","r",stdin)
    #define Close() ios::sync_with_stdio(0),cin.tie(0)
    
    typedef pair<int,int> pii;
    typedef pair<LL,LL> pll;
    
    const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
    const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
    const double pi = acos(-1.0);
    const int N = 110;
    
    const int G = 100;       //矩阵大小
    const LL MOD = 1e9 + 7;    //模数
    struct MX
    {
        int v[G+5][G+5];
        void O() { ms(v, 0); }
        void E() { ms(v, 0); for (int i = 1; i <= G; ++i)v[i][i] = 1; }
        void P()
        {
            for (int i = 1; i <= G; ++i)
            {
                for (int j = 1; j <= G; ++j)printf("%d ", v[i][j]); puts("");
            }
        }
        MX operator * (const MX &b) const
        {
            MX c; c.O();
            for (int k = 1; k <= G; ++k)
            {
                for (int i = 1; i <= G; ++i) if (v[i][k])
                {
                    for (int j = 1; j <= G; ++j)
                    {
                        c.v[i][j] = (c.v[i][j] + (LL)v[i][k] * b.v[k][j]) % MOD;
                    }
                }
            }
            return c;
        }
        MX operator + (const MX &b) const
        {
            MX c; c.O();
            for (int i = 1; i <= G; ++i)
            {
                for (int j = 1; j <= G; ++j)
                {
                    c.v[i][j] = (v[i][j] + b.v[i][j]) % MOD;
                }
            }
            return c;
        }
        MX operator ^ (LL p) const
        {
            MX y; y.E();
            MX x; memcpy(x.v, v, sizeof(v));
            while (p)
            {
                if (p&1) y = y*x;
                x = x*x;
                p>>=1;
            }
            return y;
        }
    }xishu;
    
    int n;
    LL k,f[N],a[N];
    
    int main(){
        //Open();
        Close();
        cin >> n >> k;
        rep1(i,1,n) cin >> f[i];
        rep1(i,1,n) cin >> a[i];
        rep1(i,1,n) xishu.v[n][i] = a[n-i+1];
        rep1(i,1,n-1) xishu.v[i][i+1] = 1;
        if (k<=n){
            cout << f[k]%MOD << endl;
            return 0;
        }
        xishu = xishu^(k-n);
        LL ans = 0;
        rep1(i,1,n)
            ans = (ans + xishu.v[n][i]*f[i])%MOD;
        cout << ans << endl;
        return 0;
    }
    
  • 相关阅读:
    预习非数值数据的编码方式
    预习原码补码
    C语言||作业01
    C语言寒假大作战04
    C语言寒假大作战03
    C语言寒假大作战02
    C语言寒假大作战01
    C语言|作业12—学期总结
    C语言|博客作业11
    第三章预习
  • 原文地址:https://www.cnblogs.com/AWCXV/p/7626258.html
Copyright © 2011-2022 走看看