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

    本题是一个典型的使用矩阵优化的题。
    本题的特殊之处在于:矩阵是会变化的,而不是固定的。
    所以我们要分阶段搞,而不是一下子搞。
    容易得出:
    f[i] = f[i-1] * 10 ^ k + i;
    其中k由i决定。
    变形一下原式:
    f[i] = f[i-1] * 10 ^ k + (i-1) + 1;
    容易构建矩阵:

    [egin{equation} left[ egin{array}{ccc} f[i] & i-1 & 1 end{array} ight] end{equation} ]

    和变换矩阵:

    [egin{equation} left[ egin{array}{ccc} 10^k & 0 & 0 \ 1 & 1 & 0 \ 1 & 1 & 1 end{array} ight] end{equation} ]

    套用模板即可。
    下面是代码。

    #include <bits/stdc++.h>
    using namespace std;
    long long n, m;
    #define ll long long
    struct M {
        ll v[4][4];
        M() {
            memset(v, 0, sizeof(v));
        }
        friend void print(M a) {
            for(int i = 1; i <= 3; i++) {
                for(int j = 1; j <= 3; j++) 
                    cout << a.v[i][j] << ' ';
                cout << endl;
            }
        }
        friend M operator * (M a, M b) {
            M ans;
            for(int i = 1; i <= 3; i++) {
                for(int j = 1; j <= 3; j++) {
                    for(int k = 1; k <= 3; k++) {
                        ans.v[i][j] = (ans.v[i][j] % m + (a.v[i][k]%m * b.v[k][j] % m)%m) % m;
                    }
                }
            }
           return ans;
        }
        friend M operator ^ (M a, ll b) {
            M ans;
            for(int i = 1; i <= 3; i++) ans.v[i][i] = 1;
            for(ll i = b; i; i >>= 1, a = a * a) {
                if(i & 1) ans = ans * a;
            }
            return ans;
        }
    }a, b;
    ll pow(ll a, ll b) {
        int ans = 1;
        for(int i = b; i; i >>= 1, a = a*a) 
            if(i &1) ans = ans*a;
        return ans;
    }
    int main() {
        scanf("%lld %lld", &n, &m);
        a.v[1][1]  = a.v[1][2] = 0;
        a.v[1][3] = 1;
        ll c = 10;
        ll d = 1;
        ll u = 0;
        b.v[1][1] = pow(10, d);
        b.v[2][1] =b.v[2][2]=b.v[3][1] = b.v[3][2]=b.v[3][3] = 1;
        while(c-1 < n) {
            a = a * (b ^ (pow(10, d) - u-1));
            u = pow(10, d)-1;
            d++;
            c*=10;
            b.v[1][1] = (b.v[1][1] * 10)%m;
        }
        b = b^(n-u);
        a = a*b;
        printf("%lld
    ", a.v[1][1]);
        return 0;
    }
    

    注:代码在bzoj上可以ac,但是在洛谷上不保证ac。

  • 相关阅读:
    概率统计(DP)
    iOS中几种定时器
    微信开发笔记——微信网页登录授权,获取用户信息
    swift中通知的使用
    Swift的基础,操作符,字符串和集合类型
    NSNotificationCenter
    IOS中通知中心(NSNotificationCenter)的使用总结
    Swift观察者模式
    swift中通知的使用
    Swift
  • 原文地址:https://www.cnblogs.com/gengchen/p/6337859.html
Copyright © 2011-2022 走看看