題目描述this
輸入spa
輸出blog
樣例輸入string
2
2
31io
樣例輸出class
3
343812777493853數據
題解di
費馬小定理+矩陣乘法時間
傻逼題,根據費馬小定理,指數在模 $p-1$ 意義下相等時冪數相等。while
所以求出 $2^n$ 在模 $p-1$ 意義下的結果,再用矩陣乘法維護fib數列,求矩陣的 $2^n\ \text{mod}\ (p-1)$ 次冪便可。
模數較大所以使用快(man)速乘,時間複雜度 $O(\log^2n)$ 。
#include <cstdio> #include <cstring> #define mod 1125899839733759 typedef long long ll; inline ll mul(ll x , ll y , ll p) { ll ans = 0; while(y) { if(y & 1) ans = (ans + x) % p; x = (x + x) % p , y >>= 1; } return ans; } inline ll pow(ll x , ll y , ll p) { ll ans = 1; while(y) { if(y & 1) ans = mul(ans , x , p); x = mul(x , x , p) , y >>= 1; } return ans; } struct data { ll v[2][2]; data() {memset(v , 0 , sizeof(v));} ll *operator[](int a) {return v[a];} data operator*(data a) { data ans; int i , j , k; for(i = 0 ; i < 2 ; i ++ ) for(k = 0 ; k < 2 ; k ++ ) for(j = 0 ; j < 2 ; j ++ ) ans[i][j] = (ans[i][j] + mul(v[i][k] , a[k][j] , mod)) % mod; return ans; } data operator^(ll y) { data x = *this , ans; ans[0][0] = ans[1][1] = 1; while(y) { if(y & 1) ans = ans * x; x = x * x , y >>= 1; } return ans; } }A; int main() { int T; scanf("%d" , &T); while(T -- ) { ll n; scanf("%lld" , &n) , n = pow(2 , n , mod - 1); A[0][0] = 0 , A[0][1] = A[1][0] = A[1][1] = 1 , A = A ^ n; printf("%lld\n" , A[1][0]); } return 0; }