[Cpp]
/**
* Stratege: constructor A = | 1 1 |
* | 1 0 |
* Rapid matrix power, binary summation
* Status: johnsondu B Accepted 252 KB 15 ms c ++ 3113 B
*
*/
# Include <iostream>
# Include <cstdio>
# Include <cstring>
# Include <cmath>
# Include <algorithm>
Using namespace std;
Typedef _ int64 LLD;
Struct Matrix
{
LLD mat [2] [2];
};
Matrix tmp, unit, res;
Lld k, B, n, M;
Matrix a1, a2, a3;
Matrix Multi (Matrix a, Matrix B) // multiply two matrices
{
Matrix c;
For (int I = 0; I <2; I ++)
For (int j = 0; j <2; j ++)
{
C. mat [I] [j] = 0;
For (int k = 0; k <2; k ++)
C. mat [I] [j] + = (LLD). mat [I] [k] * B. mat [k] [j], c. mat [I] [j] % = M; // when the matrix is multiplied, overflow must be prevented.
}
Return c;
}
Matrix power (LLD p) // obtain a1 = A ^ B
{
Matrix tp = unit;
Matrix tr = tmp;
While (p)
{
If (p & 1)
{
Tr = Multi (tr, tp );
P --;
Continue;
}
Tp = Multi (tp, tp );
P> = 1;
}
Return tr;
}
Matrix power1 (LLD p) // obtain a2 = A ^ k
{
Matrix tp = a2;
Matrix tr = tmp;
While (p)
{
If (p & 1)
{
Tr = Multi (tr, tp );
P --;
Continue;
}
Tp = Multi (tp, tp );
P> = 1;
}
Return tr;
}
Matrix add (Matrix a, Matrix B) // Matrix addition
{
Matrix c;
For (int I = 0; I <2; I ++)
For (int j = 0; j <2; j ++)
C. mat [I] [j] = (a. mat [I] [j] + B. mat [I] [j]) % M;
Return c;
}
Void init ()
{
Unit. mat [0] [0] = 1; // initialize the Matrix
Unit. mat [0] [1] = 1;
Unit. mat [1] [0] = 1;
Unit. mat [1] [1] = 0;
Tmp. mat [0] [0] = 1; // unit matrix
Tmp. mat [0] [1] = 0;
Tmp. mat [1] [0] = 0;
Tmp. mat [1] [1] = 1;
A1 = power (B); // ans = A ^ B + A ^ (k + B) + A ^ (2 k + B) +... + A ^ (n-1) k + B)
A2 = power (K); // then a1 = A ^ B, a2 = A ^ k, so there are ans = a1 * (E + a2 ^ 1 + a2 ^ 2 +... + a2 ^ (n-1 ));
}
Matrix MatrixSum (LLD p) // obtain E + a2 ^ 1 + a2 ^ 2 +... + a2 ^ (n-1)
{
If (p = 1) // note that when p = 1, the base is a2 = A ^ k.
Return a2;
Matrix tm, tr;
Tm = MatrixSum (p/2 );
If (p & 1)
{
Tr = power1 (p/2 + 1 );
Tm = add (tm, Multi (tm, tr ));
Tm = add (tm, tr );
}
Else {
Tr = power1 (p/2 );
Tm = add (tm, Multi (tm, tr ));
}
Return tm;
}
Void output () // output
{
If (n = 1)
{
Printf ("% I64d \ n", a1.mat [0] [1]);
Return;
}
If (n = 0)
{
Printf ("0 \ n ");
Return;
}
Matrix ans = MatrixSum (n-1); // The result is 0 ~ N-1. First, obtain 1 ~ N-1
Ans = add (ans, tmp); // obtain the sum
Ans = Multi (ans, a1); // ans = a1 * (E + a2 ^ 1 + a2 ^ 2 +... + a2 ^ (n-1 ))
Printf ("% I64d \ n", ans. mat [0] [1] % M); // output
}
Int main ()
{
While (scanf ("% I64d % I64d % I64d % I64d", & K, & B, & n, & M )! = EOF)
{
Init ();
Output ();
}
Return 0;
}
Author: zone_programming