CF - 392 C. Yet Another Number Sequence (矩阵快速幂)

CF - 392 C. Yet Another Number Sequence

题目传送门

这个题看了十几分钟直接看题解了,然后恍然大悟,发现纸笔难于描述于是乎用Tex把初始矩阵以及转移矩阵都敲了出来

\(n\le 1e17\) 这个数量级求前缀和,发现递推关系之后矩阵快速幂是可以求出来的,所以就尝试把\(A_i(k)\) 的递推式求出来。
\[
A_{i-1}(k) = F_{i-1} * (i-1) ^ k\A_{i-2}(k) = F_{i-2} * (i-2) ^ k
\]

\[
\begin{aligned}
A_i(k) =& F_i * i ^ k\ =&(F_{i-1} + F_{i-2}) * i ^ k\ =& F_{i-1} * [(i-1) + 1] ^ k + F_{i-2} * [(i-2) + 2] ^ k;\ =& \sum_{j=0}^k{C_k^j *F_{i-1} * (i-1) ^ j} + \sum_{j=0}^k{C_k^j * F_{i-2} * (i-2) ^ j * 2 ^ {k-j}}\ =& \sum_{j=0}^{k}A_{i-1}(j)*C_k^j + \sum_{j=0}^kA_{i-2}(j)*C_k^j*2^{k-j}
\end{aligned}
\]

到这里递推式就求出来了
\[
A_i(k) = \sum_{j=0}^kA_{i-1}(j) *C_k^j + \sum_{j=0}^kA_{i-2}(j)*C_k^j*2^{k-j}
\]
由于最后求得是\(\sum_{i=1}^n A_i(k)\)

所以要把它放到矩阵中,然后矩阵中其他的元素也就理所当然的可以摆出来了
\[
\begin{bmatrix}
\sum_{j=1}^i A_j(k)&A_i(0)&A_i(1)&\cdots&A_i(k)&A_{i-1}(0)&A_{i-1}(1)&\cdots A_{i-1}(k)
\end{bmatrix}
\]
然后根据递推式以及原始矩阵设计转移矩阵
\[
\begin{bmatrix}1&0&0&\cdots&0&0&0&\cdots&0\\C_k^0&C_0^0&C_1^0&\cdots&C_k^0&1&0&\cdots&0\\C_k^1&0&C_1^1&\cdots&C_k^1&0&1&\cdots&0\\\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\ddots&\vdots\\C_k^k&0&0&\cdots&C_k^k&0&0&\cdots&1\\C_k^0*2^k&C_0^0*2^0&C_1^0*2^1&\cdots&C_k^0*2^k&0&0&\cdots&0\\C_k^1*2^{k-1}&0&C_1^1*2^0&\cdots&C_k^1*2^{k-1}&0&0&\cdots&0\\\vdots&\vdots&\vdots&\ddots&\vdots&\vdots&\vdots&\ddots&\vdots\\C_k^k*2^0&0&0&\cdots&C_k^k*2^{0}&0&0&\cdots&0\end{bmatrix}
\]
可能直接放出来不好理解,那么对这个矩阵划分一下几个区

左边一列是用来求和的,中间这两部分是用来计算\(A_{i+1}^j (j\in[0,k])\) 的,右侧是用来转移\(A_{i}^j(j\in [0,k])\) 的。

最后直接矩阵快速幂就好了,整个过程细节比较多。

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 101;
const int mod = 1e9 + 7;
struct matrix{
    ll mat[N][N];
    int r,c;
    matrix(){}
    matrix(int rr,int cc){r = rr,c= cc;}
    void clear(){
        memset(mat,0,sizeof mat);
    }
};
void MOD(ll &x){x=(x%mod+mod)%mod;}
matrix operator * (const matrix&a,const matrix&b){
    matrix c(a.r,b.c);
    c.clear();
    for(int k=0;k<a.c;k++){
        for(int i=0;i<c.r;i++){
            for(int j=0;j<c.c;j++){
                MOD(c.mat[i][j] += a.mat[i][k] * b.mat[k][j] % mod);
            }
        }
    }
    return c;
}
ll C[55][55],p[55];
void prework(){
    p[0] = 1;
    for(int i=1;i<=50;i++)p[i] = p[i-1] * 2 % mod;
    for(int i=0;i<=50;i++)C[i][0] = 1;
    for(int i=1;i<=50;i++){
        for(int j=1;j<=i;j++)
           C[i][j] = (C[i-1][j] + C[i-1][j-1]) % mod;
    }
}
ll solve(ll n,ll k){
    if(n == 1)return 1;
    if(n == 2)return (p[k+1] + 1) % mod;
    ll sum = 0;
    int kk = k * 2 + 3;
    matrix x(1,kk),y(kk,kk);
    x.mat[0][0] = (p[k+1] + 1) % mod;
    for(int i=0;i<=k;i++){
        x.mat[0][i+1] = p[i+1];
        x.mat[0][i+k+2] = 1;
    }
    y.mat[0][0] = 1;
    for(int i=0;i<=k;i++){
        y.mat[i+1][0] = C[k][i];
        y.mat[i+k+2][0] = C[k][i] * p[k-i] % mod;
        y.mat[i+1][i+k+2] = 1;
    }
    for(int i=0;i<=k;i++){
        for(int j=0;j<=i;j++){
            y.mat[j+1][i+1] = C[i][j];
            y.mat[j+k+2][i+1] = C[i][j] * p[i-j] % mod;
        }
    }
    n -= 2;
    for(;n;n >>= 1){
        if(n & 1)x = x * y;
        y = y * y;
    }
    return x.mat[0][0];
}
int main(){
    ll n,k;
    prework();
    scanf("%lld%lld",&n,&k);
    printf("%lld\n",solve(n,k));
    return 0;
}

原文地址:https://www.cnblogs.com/1625--H/p/11664067.html

时间: 2024-10-10 10:06:57

CF - 392 C. Yet Another Number Sequence (矩阵快速幂)的相关文章

Uva10689 Yet another Number Sequence ( 矩阵快速幂 )

Uva 10689Yet another Number Sequence(  矩阵快速幂  ) 题意: 就是矩阵快速幂,没什么好说的. 分析: 其实还是斐波那契数列.只是最后对应的矩阵不是(1,1)是(a,b)了 MOD = 1; for( int i = 0; i < m; ++i ) MOD *= 10; 代码 #include <cstdio> #include <cstring> #include <algorithm> using namespace s

UVA - 10689 Yet another Number Sequence 矩阵快速幂

                  Yet another Number Sequence Let’s de?ne another number sequence, given by the following function:f(0) = af(1) = bf(n) = f(n − 1) + f(n − 2), n > 1When a = 0 and b = 1, this sequence gives the Fibonacci Sequence. Changing the values

HDU 1005 Number Sequence 矩阵快速幂

Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 236241    Accepted Submission(s): 60070 Problem Description A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A

SDUT1607:Number Sequence(矩阵快速幂)

题目:http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=1607 题目描述 A number sequence is defined as follows: f(1) = 1, f(2) = 1, f(n) = (A * f(n - 1) + B * f(n - 2)) mod 7. Given A, B, and n, you are to calculate the value of f(n). 输入

UVA 10689 Yet another Number Sequence 矩阵快速幂 水呀水

#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int N = 4; int Mod; int msize; struct Mat { int mat[N][N]; }; Mat operator *(Mat a, Mat b) { Mat c; mems

uva 11651 - Krypton Number System(矩阵快速幂)

题目链接:uva 11651 - Krypton Number System 题目大意:给定进制base,和分数score,求在base进制下,有多少个数的值为score,要求不能有连续相同的数字以及前导0.计算一个数的值即为相邻两位数的平方差和. 解题思路:因为score很大,所以直接dp肯定超时,但是即使对于base=6的情况,每次新添一个数score最大增加25(0-5),所以用dp[i][j]预处理出base平方以内的总数,然后用矩阵快速幂计算. #include <cstdio> #

hdu-5667 Sequence(矩阵快速幂+费马小定理+快速幂)

题目链接: Sequence Time Limit: 2000/1000 MS (Java/Others)     Memory Limit: 65536/65536 K (Java/Others) Problem Description Holion August will eat every thing he has found. Now there are many foods,but he does not want to eat all of them at once,so he fi

HDU5950-Recursive sequence(矩阵快速幂)

题目链接:Recursive sequence 题意:给出n头母牛,第一头报a,第二头报b,第i头报f[i-2]*2+f[i-1]+i^4,问第n头母牛报数多少 分析:N,a,b<2^31,果断矩阵快速幂,关键是要推出公式,公式如下,仅作参考 1 0 0 0 0 0 0        1               1 1 1 0 0 0 0 0        i                i+1 1 2 1 0 0 0 0       i2              (i+1)2 1 3

zoj3690--Choosing number(dp,矩阵快速幂)

Choosing number Time Limit:2000MS     Memory Limit:65536KB     64bit IO Format:%lld & %llu Submit Status Description There are n people standing in a row. And There are m numbers, 1.2...m. Every one should choose a number. But if two persons standing