【图灵杯 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;
}
posted @ 2017-10-04 18:44  AWCXV  阅读(189)  评论(0编辑  收藏  举报