2019牛客暑期多校训练营(第五场)B generator 1 (矩阵的快速幂)

题目描述 

You are given four positive integers x_0, x_1, a, bx0​,x1​,a,b. And you know x_i = a \cdot x_{i-1} + b \cdot x_{i-2}xi​=a⋅xi−1​+b⋅xi−2​ for all i \ge 2i≥2.

Given two positive integers n, and MOD, please calculate x_nxn​ modulo MOD.

Does the problem look simple? Surprise! The value of n may have many many digits!

输入描述:

The input contains two lines.
The first line contains four integers x_0, x_1, a, bx0​,x1​,a,b (1 \le x_0, x_1, a, b \le 10^91≤x0​,x1​,a,b≤109).
The second line contains two integers n, MOD (1 \le n < 10^{(10^6)}, 10^9 < MOD \le 2 \times 10^91≤n<10(106),109

输出描述:

Print one integer representing the answer.

示例1

输入

复制

1 1 1 1
10 1000000001

输出

复制

89

说明

The resulting sequence x is Fibonacci sequence. The 11-th item is 89.

示例2

输入

复制

1315 521 20185 5452831
9999999999999999999999999999999999999 1000000007

输出

复制

914730061

思路:拆成十进制快速幂+二进制快速幂,直接看代码就能懂。


#include
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=a;i>=b;--i)
using namespace std;
typedef long long ll;
//typedef vector vec;
//typedef vector mat;
const int MAXN = 1e6+50;
const int INF = 0x3f3f3f3f;
struct mat{
    ll m[2][2];
    mat(){memset(m, 0, sizeof(m));}
};

ll t, mod;
char n[MAXN];
mat mul(mat &A, mat &B){
    mat C;
    for(int i = 0; i < 2; i++){
        for(int k = 0; k < 2; k++){
            for(int j = 0; j < 2; j++){
                C.m[i][j] = (C.m[i][j] + A.m[i][k] * B.m[k][j]) % mod;
            }
        }
    }
    return C;
}
mat pow2(mat A, int p){
    mat B;
    for(int i = 0; i < 2; i++)
        B.m[i][i] = 1;
    while(p){
        if(p&1) B = mul(B, A);
        A = mul(A, A);
        p >>= 1;
    }
    return B;
}
mat pow10(mat A, char *p){
    int l = strlen(p) - 1;
    mat B;
    for(int i = 0; i < 2; i++)
        B.m[i][i] = 1;
    per(i, l, 0){
        if(p[i]-'0'>0){
            B = mul(B, pow2(A, p[i]-'0'));
        }
        A = pow2(A, 10);
    }
    return B;
}
int main() {
	//ios::sync_with_stdio(false);
    ll x0, x1, a, b;

    scanf("%lld%lld%lld%lld", &x0, &x1, &a, &b);
    mat mm;
    mm.m[0][0] = a; mm.m[0][1] = b;
    mm.m[1][0] = 1; mm.m[1][1] = 0;
    scanf("%s%lld", n, &mod);
    mm = pow10(mm, n);
    ll ans = ((x1*mm.m[1][0])%mod + (x0*mm.m[1][1])%mod)%mod;
    printf("%lld\n", ans);

	return 0;
}
/**/

 

你可能感兴趣的:(快速幂)