Reading comprehension HDU - 4990

原题链接

  • 题意:多组输入,输入 \(1 <= n ,m <=1000000000\)\(ans=0\) ,当 \(ans\) 为偶数, \(ans = ans\times 2 + 1\),如果 \(ans\) 为奇数,那么 \(ans = ans\times 2\)。输出 \(ans\)

  • 题解:可以发现,答案要么是 \(2\times ans\) ,即只有系数起作用,要么是 \(2\times ans + 1\) ,即有一个 \(1\) 起作用,那么就可以构造 \(ANS\) 矩阵了。
    \(\begin{bmatrix}ans&0\\1&0\end{bmatrix}\) 然后发现其实,系数矩阵有两个,但是这两个的\(a_{1,1}\)一定是 \(2\),然后为了维护 \(ANS\) 矩阵的 \(a_{2,1}=1\),所有的系数矩阵\(a_{2,2} = 1\),很容易得算出,如果要对 \(ans\) 乘二加一,显然系数矩阵的 \(a_{1, 2} = 1\) 否则 \(a_{1, 2} = 0\),然后得到两个系数矩阵 \(A = \begin{bmatrix}2&1\\0&1\end{bmatrix}, B = \begin{bmatrix}2&0\\0&1\end{bmatrix}\) 同时那么知道了系数矩阵,所以就可以用快速幂加速了,尽管有两个稀疏矩阵,其实发现他们相乘的数量都是 \(\left \lfloor \frac{n}{2} \right \rfloor\),就是 \(A\) 矩阵, 如果 \(n%2 = 1\) 的话 \(A\) 矩阵还要再左乘一下。

  • 代码:

#include <iostream>
#include <cstring>

using namespace std;


typedef long long ll;
const int N = 1e3  + 9;
ll mod = 6;
ll n, m;
struct Matrix {
    ll a[10][10];
    Matrix(){memset(a, 0, sizeof a);}
    Matrix operator*(Matrix rhs)const {
        Matrix ret;
        for (int i = 0; i < 2; i ++) {
            for (int j = 0; j < 2; j++){
                for (int k = 0; k < 2; k++) {
                    (ret.a[i][j] += (a[i][k] * rhs.a[k][j] % mod)) %= mod;
                }
            }
        }
        return ret;
    }
    void pr() {
        for (int i = 0; i < 2; i ++) {
            for (int j = 0; j < 2; j++){
                cout << a[i][j] << " ";
            }
            cout << endl;
        }
    }
};
Matrix ksm (Matrix A, int kk) {
    if (kk == 1)return A;
    Matrix ret;
    bool f = 0;
    while (kk) {
        if (kk & 1) {
            if (!f) {
                ret = A;
                f = 1;
            } else
            ret = ret * A;
        }
        kk >>= 1;
        A = A * A;
    }
    return ret;
}
void solve() {
    ll a[2][2] = 
    {  
        {2, 1}, 
        {0, 1} 
    };
    ll b[2][2] = 
    {
        {2, 0},
        {0, 1}
    };
n = 0;
while (cin >> n >> m) {
    mod = m;
    Matrix A, B;
    for (int i = 0; i  < 2; i++) {
        for (int j = 0; j < 2; j++) {
            A.a[i][j] = a[i][j];
            B.a[i][j] = b[i][j];
        }
    }
    Matrix C = A*B;
    n--;
    ll k = n/2;
    Matrix ans;
    ans.a[1][0] = 1;
    ans.a[0][0] = 1;
    if (k != 0) {
        C = ksm(C, k);
        ans = C * ans;
    }
    if (n % 2) {
        ans = B * ans;
    }
    if (m == 1)cout << 0 << endl;
    else 
    cout << ans.a[0][0] << endl;
}
}
signed main() {
    int t = 1;//cin >> t;
    while (t--) {
        solve();
    }
}

posted @ 2021-03-26 21:24  u_yan  阅读(48)  评论(0编辑  收藏  举报