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(10100000010^{1000000})。但是個數存不下來,轉二進制又非常麻煩。

那麼咋辦?可以直接用十進制來做呀,我們回顧一下二進制快速冪就是取二進制每一位是1的時候,把乘冪處理好的底數乘上去。由於二進制每位只有兩個選擇,所以比較簡單。

十進制也完全可以處理底數base=base10base = base^{10},但是二進制每一位還有9個選擇,那也好辦,如果這一位是xxres=res×(base10)xres =res \times (base^{10})^{x}

這樣的每次乘冪的次數就降低到1010以下了,這個乘冪還是有必要二進制快速冪一下,這題卡這個是嚴了一點。但是這樣也避免了全局轉二進制太麻煩,而且複雜度也不至於太高。

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

#include <bits/stdc++.h>

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;
}
/*




 * */
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章