Sequence 矩陣快速冪 + 費馬小定理
阿新 • • 發佈:2018-12-12
f[1] = 1
f[2] = a ^ b
其實不是很好的去想到取log的
兩邊同時取log
然後 F[2] = b F[1] = 0
則 f[n] = a^(F[n]) % p
費馬小定理 :
① 判斷素數,對於大素數的判定,Miller-Rabin 素數判定 ②求解逆元 ,設a模p的逆元為x,則a*x≡1(mod p) ,(a,p)=1;由費馬小定理可以知道x=a^(p-2) ③對於計算ab(modp)ab(modp) 可簡化 對於素數p,任取跟他互素的數a,有a^(p-1)(mod p)=1 所以任取b,有a^b%p=a^(b%(p-1))(%p)從而簡化運算。
本文來自 楊美人 的部落格 ,全文地址請點選:https://blog.csdn.net/qq_40679299/article/details/80596406?utm_source=copy
然後 f[n] = a^(F[n] mod (p - 1) ) mod p
程式碼:
// // HDU5667 - Sequence.cpp // 數論 // // Created by Terry on 2018/9/29. // Copyright © 2018年 Terry. All rights reserved. // #include <stdio.h> typedef long long LL; long long read(){ long long x = 0, f = 1; char ch=getchar(); while(ch < '0' || ch > '9'){if(ch=='-') f = -1; ch = getchar();} while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0'; ch = getchar();} return x * f; } const int maxn = 3; LL mod; struct Matrix{ long long int m[maxn][maxn]; }unit; Matrix operator * (Matrix a, Matrix b){ Matrix ret; LL x; int n = 3; for(int i = 0; i < n; ++i){ for(int j = 0; j < n; ++j){ x = 0; for(int k = 0; k < n; ++k){ x += ((LL)a.m[i][k] * b.m[k][j]) % mod; } ret.m[i][j] = x % mod; } } return ret; } void init_unit(){ // 單位矩陣 for(int i = 0; i < maxn; ++i){ unit.m[i][i] = 1; } } Matrix pow_mat(Matrix a, LL n){ Matrix ans = unit; while (n) { if(n & 1){ ans = ans * a; } a = a * a; n >>= 1; } return ans; } LL multi(LL a, LL b, LL Mod){ // a * b % Mod LL ret = 0; while(b > 0){ if(b & 1){ ret = (ret + a) % Mod; } b >>= 1; a = (a << 1) % Mod; } return ret; } LL quick_mod(LL a, LL b, LL Mod){ LL ans = 1; while(b){ if(b & 1){ ans = multi(ans, a, Mod); b--; } b /= 2; a = multi(a, a, Mod); } return ans; } int main(){ init_unit(); LL T = read(); while (T--) { LL n = read(); LL a = read(); LL b = read(); LL c = read(); mod = read(); if(n == 1){ printf("1\n"); } else if(n == 2){ printf("%lld\n", quick_mod(a, b, mod)); } else{ if(a % mod == 0){ printf("0\n"); continue; } Matrix ans, A; A.m[0][0] = c; A.m[0][1] = 1; A.m[0][2] = 0; A.m[1][0] = 1; A.m[1][1] = 0; A.m[1][2] = 0; A.m[2][0] = 1; A.m[2][1] = 0; A.m[2][2] = 1; ans.m[0][0] = b; ans.m[0][1] = 0; ans.m[0][2] = b; mod--; // 費馬小定理 A = pow_mat(A, n - 2); ans = ans * A; mod++; printf("%lld\n", quick_mod(a, ans.m[0][0]%(mod - 1), mod)); } } return 0; }