noip模拟赛 残
分析:这道题有点丧病啊......斐波那契数列本来增长就快,n <= 10^100又套2层,看到题目就让人绝望.不过这种题目还是有套路的.首先求斐波那契数列肯定要用到矩阵快速幂,外层的f可以通过取模来变小,可是里面的f不能直接取模1e9+7.因为余数最多就1e9+7种,所以肯定有一个循环节,打表发现内层f的循环节是2000000016,x的循环节是(1e9+7)*3,在求得时候mod循环节长度就ok了.
关于斐波那契的一些套路要记住:用矩阵快速幂加速、有循环节......
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; const long long mod = 1000000007; const long long mod2 = mod * 2 + 2; const long long mod3 = mod2 * 3; typedef long long ll; int T, len, shu[210]; char s[210]; ll t; struct node { ll a[3][3]; node(){ memset(a, 0, sizeof(a)); } }x, y; ll zhuanhuan() { ll res = 0; for (int i = 1; i <= len; i++) shu[i] = s[i] - '0'; for (int i = 1; i <= len; i++) res = (res * 10 + shu[i]) % mod3; return res; } node mul1(node x, node y) { node p; memset(p.a, 0, sizeof(p.a)); for (int i = 1; i <= 2; i++) for (int j = 1; j <= 2; j++) for (int k = 1; k <= 2; k++) p.a[i][j] = (p.a[i][j] + x.a[i][k] * y.a[k][j] % mod2) % mod2; return p; } node mul2(node x, node y) { node p; memset(p.a, 0, sizeof(p.a)); for (int i = 1; i <= 2; i++) for (int j = 1; j <= 2; j++) for (int k = 1; k <= 2; k++) p.a[i][j] = (p.a[i][j] + x.a[i][k] * y.a[k][j] % mod) % mod; return p; } ll qpow1(ll b) { x.a[1][1] = 0; x.a[1][2] = 1; y.a[1][1] = 0; y.a[1][2] = y.a[2][1] = y.a[2][2] = 1; while (b) { if (b & 1) x = mul1(x, y); y = mul1(y, y); b >>= 1; } return x.a[1][1]; } ll qpow2(ll b) { x.a[1][1] = 0; x.a[1][2] = 1; y.a[1][1] = 0; y.a[1][2] = y.a[2][1] = y.a[2][2] = 1; while (b) { if (b & 1) x = mul2(x, y); y = mul2(y, y); b >>= 1; } return x.a[1][1]; } int main() { scanf("%d", &T); while (T--) { scanf("%s", s + 1); len = strlen(s + 1); t = zhuanhuan(); t = qpow1(t); printf("%lld\n", qpow2(t)); } return 0; }