Codeforces 551D GukiZ and Binary Operations(矩阵快速幂)
转自http://www.cnblogs.com/keam37/p/4578568.html
1 /*Author :usedrose */ 2 /*Created Time :2015/8/7 12:26:39*/ 3 /*File Name :2.cpp*/ 4 #pragma comment(linker, "/STACK:1024000000,1024000000") 5 #include <cstdio> 6 #include <iostream> 7 #include <algorithm> 8 #include <sstream> 9 #include <cstdlib> 10 #include <cstring> 11 #include <climits> 12 #include <vector> 13 #include <string> 14 #include <ctime> 15 #include <cmath> 16 #include <deque> 17 #include <queue> 18 #include <stack> 19 #include <set> 20 #include <map> 21 #define INF 0x3f3f3f3f 22 #define eps 1e-8 23 #define pi acos(-1.0) 24 #define MAXN 1110 25 #define MAXM 100110 26 #define OK cout << "ok" << endl; 27 #define o(a) cout << #a << " = " << a << endl 28 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 29 using namespace std; 30 typedef long long ll; 31 32 const int N = 2; 33 ll n, k, l, m; 34 35 struct Mat { 36 ll mat[N + 1][N + 1]; 37 } A, B; 38 39 Mat operator * ( Mat a, Mat b ) 40 { 41 Mat c; 42 memset ( c.mat, 0, sizeof c.mat ); 43 for ( int k = 0; k < N; k++ ) 44 for ( int i = 0; i < N; i++ ) 45 for ( int j = 0; j < N; j++ ) 46 ( c.mat[i][j] += ( a.mat[i][k] * b.mat[k][j] ) % m ) %= m; 47 return c; 48 } 49 50 Mat operator ^ ( Mat a, ll pow ) 51 { 52 Mat c; 53 for ( int i = 0; i < N; i++ ) 54 for ( int j = 0; j < N; j++ ) 55 c.mat[i][j] = ( i == j ); 56 while ( pow ) { 57 if ( pow & 1 ) c = c * a; 58 a = a * a; 59 pow >>= 1; 60 } 61 return c; 62 } 63 64 ll quickp( ll x ) 65 { 66 ll s = 1, c = 2; 67 while( x ) { 68 if( x & 1 ) s = ( s * c ) % m; 69 c = ( c * c ) % m; 70 x >>= 1; 71 } 72 return s; 73 } 74 75 int main() 76 { 77 //freopen("data.in","r",stdin); 78 //freopen("data.out","w",stdout); 79 cin.tie(0); 80 ios::sync_with_stdio(false); 81 Mat p, a; 82 p.mat[0][0] = 0, p.mat[0][1] = 1; 83 p.mat[1][0] = 1, p.mat[1][1] = 1; 84 a.mat[0][0] = 1, a.mat[0][1] = 2; 85 a.mat[1][0] = 0, a.mat[1][1] = 0; 86 cin >> n >> k >> l >> m; 87 ll ans = 0; 88 if (l == 64 || (1uLL<<l) > k ) { 89 ans++; 90 p = p ^ n; 91 a = a * p; 92 ll t1 = a.mat[0][0], t2 = (m + quickp(n) - t1)%m; 93 for (int i = 0;i < l; ++ i) { 94 if ((1uLL<<i)&k) 95 ans = (ans*t2)%m; 96 else ans = (ans*t1)%m; 97 } 98 } 99 cout << ans%m << endl; 100 101 return 0; 102 }