2019.8.1 牛客多校第五场

index > 牛客多校第五场


题号 标题 通过率 做法 状态
A digits 2 1017/2383 签到 √+
B generator 1 555/3660 矩阵快速幂/十进制优化
C generator 2 37/626
D generator 3 4/23
E independent set 1 45/110
F maximum clique 1 93/838
G subsequence 1 522/2513 dp √-
H subsequence 2 286/1366
I three points 1 139/2701
J three points 2 7/76
  • 代表赛后补题
  • √+ 代表赛内我通过的
  • √- 代表赛内不是我做的
  • √-○代表赛内不是我做的,补了

A - digits 2

好像我们脑子也不是转得很快,所以还是废了点功夫才想到拼接。

B - generator 1

比赛时莫名其妙地以为,矩阵乘法也可以欧拉降幂。然后从头wa到结束。

其实用了一个很巧妙的想法。

题意就是给一个公式(显然是用二维矩阵快速幂求的)。然后给你一个无比庞大的n( 1 0 1000000 10^{1000000} 101000000)。但是个数存不下来,转二进制又非常麻烦。

那么咋办?可以直接用十进制来做呀,我们回顾一下二进制快速幂就是取二进制每一位是1的时候,把乘幂处理好的底数乘上去。由于二进制每位只有两个选择,所以比较简单。

十进制也完全可以处理底数 b a s e = b a s e 10 base = base^{10} base=base10,但是二进制每一位还有9个选择,那也好办,如果这一位是 x x x r e s = r e s × ( b a s e 10 ) x res =res \times (base^{10})^{x} res=res×(base10)x

这样的每次乘幂的次数就降低到 10 10 10以下了,这个乘幂还是有必要二进制快速幂一下,这题卡这个是严了一点。但是这样也避免了全局转二进制太麻烦,而且复杂度也不至于太高。

#define _debug(x) cerr<<#x<<" = "<

#include 

using namespace std;
typedef long long ll;


template<typename _Tp, const int MAXMatrixSize>
struct Matrix {
    _Tp m[MAXMatrixSize][MAXMatrixSize];
    _Tp mod = 0;

    Matrix() {
        memset(m, 0, sizeof m);
    }

    Matrix(int _mod) : mod(_mod) {
        memset(m, 0, sizeof m);
    }

    void init1() {
        //*this = Matrix(mod);
        set(0, 0, 1);
        set(1, 1, 1);
//        for (int i = 0; i < MAXMatrixSize; i++)
//            m[i][i] = 1;
    }

    inline void set(const int &r, const int &c, const _Tp &v) { this->m[r][c] = v; }

    inline _Tp get(const int &r, const int &c) { return this->m[r][c]; }

    inline void setMod(const _Tp &_mod) { this->mod = _mod; }

    inline Matrix operator*(const Matrix t) {
        Matrix res(mod);//= Matrix(mod);
        res.setMod(mod);
        for (int i = 0; i < MAXMatrixSize; i++)
            for (int j = 0; j < MAXMatrixSize; j++)
                for (int k = 0; k < MAXMatrixSize; k++)
                    res.m[i][j] = (res.m[i][j] + m[i][k] * t.m[k][j]) % mod;
        return res;
    }
};

typedef Matrix<ll, 2> mat;

mat A, B;
ll x0, x1, a, b;
ll mo, len;
char n[1000059];

inline mat fpow(mat base, ll exp) {
    mat res(mo);
    res.init1();
    while (exp) {
        if (exp & 1)res = res * base;
        exp >>= 1;
        base = base * base;
    }
    return res;
}

inline ll calc() {

    len = strlen(n);
    //reverse(n, n + len);

    mat res(mo);
    res.init1();
    mat base = B;

    for (int i = len - 1; i >= 0; --i) {
        if (n[i] > '0')
            res = res * fpow(base, n[i] - '0');
        base = fpow(base, 10);
    }

    res = A * res;
    return res.get(0, 0);
}


int main() {

    scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
    scanf("%s %lld", n, &mo);

    A = mat(mo);
    A.set(0, 0, x0);
    A.set(0, 1, x1);

    B = mat(mo);
    B.set(0, 0, 0);
    B.set(0, 1, b);
    B.set(1, 0, 1);
    B.set(1, 1, a);

    printf("%lld\n", calc());
    return 0;
}
/*




 * */

你可能感兴趣的:(小结)