BZOJ 2326 HNOI 2011 数学作业 矩阵乘法求数列第n项


对于fn=12345678910...n,有fn=fn-1*(10^(floor(lgn)+1))+n。

所以构造矩阵:

10^(floor(lgn)+1) 0 0

1                 1 0

0                 1 1

实际上,对于1位数就是10^1,2位数就是10^2。每次矩阵乘够10^i-10^(i-1)即可,其中i表示位数,最后一次乘的次数不一样.

发现换了一种写法程序就麻烦了好多。。。

#include <cstdio>   
#include <cstring>   
#include <iostream>   
#include <algorithm>   
using namespace std;
typedef unsigned long long ll;  
#define FOR(i,j,k) for(i=j;i<=k;i++)
ll read() {
    ll s = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while ('0' <= ch && ch <= '9') s = s * 10 + ch - '0', ch = getchar();
    return s;
}
ll n, p;
struct Matrix {  
    ll a[4][4];
    Matrix(int flag) {
        int i, j;
        FOR(i,1,3) FOR(j,1,3) a[i][j] = flag & (i == j);
    }
    Matrix(bool, ll digit) {
        a[1][1] = digit;
        a[2][1] = a[2][2] = a[3][2] = a[3][3] = 1;
        a[1][3] = a[1][2] = a[2][3] = a[3][1] = 0;
    }
    ll* operator [] (int x) { return a[x]; }
    friend void operator *= (Matrix &x, Matrix y) {
        int i, j, k;
        Matrix z(0);
        FOR(i,1,3) FOR(j,1,3) FOR(k,1,3)
            z[i][j] = (z[i][j] + x[i][k] * y[k][j]) % p;
        x = z;
    }
    friend Matrix operator ^(Matrix x, ll y) {
        Matrix re(1);
        for (; y; x *= x, y >>= 1) if(y & 1) re *= x;
        return re;
    }
} ans(1);
int main() {
    ll i;
    n = read(); p = read();
    for (i = 10; i <= n; i *= 10)
        ans *= Matrix(1, i % p) ^ (i - i / 10);
    ans *= Matrix(1, i % p) ^ (n - i / 10 + 1);
    printf("%llu", (ans[2][1] + ans[3][1]) % p);
    return 0;
}  



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值