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

那玩意儿一看就要分段统计,递推式可以求一求
$F[n] = 10^k * F[n-1] +n$
这东西是可以装进矩阵的,矩阵里存三个元素, F[n],n,1
快速幂乘着玩儿就行了

/**************************************************************
    Problem: 2326
    User: di4CoveRy
    Language: C++
    Result: Accepted
    Time:24 ms
    Memory:1292 kb
****************************************************************/

#include 
using namespace std;
typedef long long LL;
struct Mat{ LL d[4][4]; }A,B,id;
LL n,m,ans;

inline void inc(LL &x,LL y) { x = ( x + y + m) % m; }   
Mat operator * (Mat p1, Mat p2) {
    Mat ret = id;
    for (int i=1;i<=3;i++)
        for (int j=1;j<=3;j++)
            for (int k=1;k<=3;k++) inc( ret.d[i][j], p1.d[i][k] * p2.d[k][j] % m );
    return ret;
}

struct PlanB {

    LL ten[20];

    inline LL w(LL x) {
        int ret = 0;
        while (x) x /= 10 , ret++;
        return ret;
    }

    Mat momsen(LL k) {
        Mat ret = id;
        ret.d[1][1] = ten[k] % m;
        ret.d[2][1] = ret.d[2][2] = 1;
        ret.d[3][1] = ret.d[3][2] = ret.d[3][3] = 1;
        return ret;
    }

    Mat qp(Mat A,LL b) {
        if (b == 1) return A;
        if (b % 2 == 0) {
            Mat t = qp(A,b>>1);
            return t * t;
        } else {
            Mat t = qp(A,b-1);
            return t * A;
        }
    }

    void solve() {
        cin >> n >> m;

        ten[0] = 1LL;
        for (int i=1;i<=w(n)+1;i++) ten[i] = ten[i-1] * 10LL;

        A.d[1][3] = 1LL;

        LL tmp = n;
        for (LL k=1;k1]));
            tmp -= (ten[k]-ten[k-1]);
        }

        B = momsen(w(n));
        if (tmp) A = A * qp(B, tmp);

        cout << A.d[1][1] << endl;
    }
}planB;

int main() {
    #ifndef ONLINE_JUDGE
        freopen("1.in","r",stdin);
    #endif
    planB.solve();
    return 0;
} 

你可能感兴趣的:(数学)