BZOJ2326 [HNOI2011]数学作业 【矩阵快速幂】

本文介绍了一种利用矩阵快速幂解决特定数列问题的方法。通过定义矩阵递推式,将复杂度较高的直接计算转化为更高效的指数级运算。适用于求解大规模数列问题,特别是当涉及到模意义下的计算时。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1318028-20180202131605812-1454415690.jpg

题解

我们设f[i]表示前i个数模M意义下的答案
则f[i] = f[i - 1] * 100...0 + i【i是几位就有几个0】
可以写出矩阵递推式:
1318028-20180202132126031-1611372976.png

之后按位数分组矩乘就好了

#include<iostream>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long int
#define REP(i,n) for (int i = 1; i <= (n); i++)
#define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
#define cls(s) memset(s,0,sizeof(s))
using namespace std;
const int maxn = 100005,maxm = 100005,INF = 1000000000;
LL N,M;
struct Matrix{
    LL s[3][3],n,m;
    Matrix(){cls(s); n = m = 0;}
}A,F;
Matrix operator *(const Matrix& a,const Matrix& b){
    Matrix ans;
    if (a.m !=b.n) return ans;
    ans.n = a.n; ans.m = b.m;
    for (int i = 0; i < ans.n; i++)
        for (int j = 0; j < ans.m; j++)
            for (int k = 0; k < a.m; k++)
                ans.s[i][j] = (ans.s[i][j] + a.s[i][k] * b.s[k][j] % M) % M;
    return ans;
}
Matrix qpow(Matrix a,LL b){
    Matrix ans; ans.n = ans.m = a.n;
    for (int i = 0; i < ans.n; i++) ans.s[i][i] = 1;
    for (; b; b >>= 1,a = a * a)
        if (b & 1) ans = ans * a;
    return ans;
}
int S[][3] = {
    {1,1,1},
    {0,1,1},
    {0,0,1}
};
int main(){
    cin >> N >> M;
    A.n = A.m = 3;
    for (int i = 0; i < 3; i++)
        for (int j = 0; j < 3; j++)
            A.s[i][j] = S[i][j];
    F.n = 3; F.m = 1;
    F.s[0][0] = 0; F.s[1][0] = 0; F.s[2][0] = 1;
    for (LL bit = 1; ; bit *= 10){
        A.s[0][0] = bit % M * 10 % M;
        if (N < bit * 10){
            F = qpow(A,N - bit + 1) * F;
            break;
        }else F = qpow(A,bit * 10 - bit) * F;
    }
    cout << F.s[0][0] << endl;
    return 0;
}

转载于:https://www.cnblogs.com/Mychael/p/8404702.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值