zoukankan      html  css  js  c++  java
  • bzoj2326 [HNOI2011]数学作业

    分析:设f[i]为1~i组成的数,可以得到f[i] = f[i-1] * 10^k + i.对于一个序列求第n项,一般可以用矩阵乘法来加速,但是每一个矩阵只能对应一个不变的递推式,这个式子中的k会变,那怎么办呢?那么在1~9,10~99,100~999每一次构造一个矩阵就好了,具体的矩阵如下:

    f(i + 1)         f(i)      10^k,1,1

        i        =     i - 1    *    0, 1, 1

        1         1      0, 0, 1

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    
    using namespace std;
    
    long long n, m,i,ans[10][10],temp[10][10],t[10][10];
    
    void mul1()
    {
        memset(t, 0, sizeof(t));
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                for (int k = 1; k <= 3; k++)
                {
            t[i][j] += ans[i][k] * temp[k][j];
            t[i][j] %= m;
                }
        memcpy(ans, t, sizeof(ans));
    }
    
    void mul2()
    {
        memset(t, 0, sizeof(t)); 
        for (int i = 1; i <= 3; i++)
            for (int j = 1; j <= 3; j++)
                for (int k = 1; k <= 3; k++)
                {
            t[i][j] += temp[i][k] * temp[k][j];
            t[i][j] %= m;
                }
        memcpy(temp, t, sizeof(temp));
    }
    
    void qpow(long long b)
    {
        while (b){
            if (b & 1)
                mul1();
            b >>= 1;
            mul2();
        }
    }
    
    int main()
    {
        scanf("%lld%lld", &n, &m);
        ans[1][3] = 1;
        for (i = 1; i <= (n + 1) / 10; i *= 10)
        {
            memset(temp, 0, sizeof(temp));
            ans[1][2] = i % m;
            temp[1][1] = (i * 10) % m;
            temp[2][1] = temp[2][2] = temp[3][2] = temp[3][3] = 1;
            qpow(i * 9);
        }
        if (i <= n)
        {
            memset(temp, 0, sizeof(temp));
            ans[1][2] = i % m;
            temp[1][1] = i * 10 % m;
            temp[2][1] = temp[2][2] = temp[3][2] = temp[3][3] = 1;
            qpow(n - i + 1);
        }
        printf("%lld
    ", ans[1][1]); 
    
        return 0;
    }
  • 相关阅读:
    2017已过半,这半年,你累吗?
    2017已过半,这半年,你累吗?
    2017已过半,这半年,你累吗?
    程序员的一个好习惯,你有几个?
    程序员的一个好习惯,你有几个?
    程序员的一个好习惯,你有几个?
    深拷贝与浅拷贝
    understanding android build layer · Dylan
    Markdown语法
    npm参考手册
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7545028.html
Copyright © 2011-2022 走看看