这题就是一个矩阵快速幂,但是后面还有一项,重点在对这个项的处理上面,关于这个项的处理,可以看另一篇blog(https://www.cnblogs.com/DynastySun/p/9462847.html),这上面有关于那个项的一些特点。我们可以观察多,这个项的变化规律,P/n(向下取整),当n越小的时候,这个值变化的越频繁,当n越大,这个值变化的越小。这就好办了,对于变化频繁的一段我们直接使用递推式子,将前50000项打表打出来,后面的变化不那么频繁的,我们就使用矩阵快速幂求解就可以了。这个题就是代码会有点多(重要部分,代码中已经给出解释):
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef long long LL; 5 6 const LL MOD = 1e9+7; 7 const int maxn = 500000; 8 9 LL A, B, C, D, n, P, F[maxn]; 10 11 void init() 12 { 13 F[1] = A; 14 F[2] = B; 15 for(int i = 3; i < maxn; ++i) 16 F[i] = (C*F[i-2]%MOD + D*F[i-1]%MOD + P/i)%MOD; 17 } 18 19 void mut(LL a[][3], LL b[][3]){ 20 LL t[3][3]; 21 memset(t, 0, sizeof(t)); 22 for(int i = 0; i < 3; ++i) 23 for(int j = 0; j < 3; ++j) 24 for(int k = 0; k < 3; ++k) 25 t[i][j] = (t[i][j] + a[i][k]*b[k][j]%MOD)%MOD; 26 memcpy(a, t, sizeof(t)); 27 } 28 29 LL quick_pow(LL a, LL b, LL c, LL m) 30 { 31 LL ans[][3] = {{1,0,0},{0,1,0},{0,0,1}}; 32 LL t[][3] = {{D,C,1},{1,0,0},{0,0,1}}; 33 while(m){ 34 if(m&1) mut(ans, t); 35 mut(t, t); 36 m >>= 1; 37 } 38 return (ans[0][0]*a%MOD + ans[0][1]*b%MOD + ans[0][2]*c)%MOD; 39 } 40 41 int main(){ 42 int T; 43 cin >> T; 44 while(T--) 45 { 46 cin >> A >> B >> C >> D >> P >> n; 47 init(); 48 if(n < maxn) 49 { 50 printf("%lld\n", F[n]); 51 } 52 else 53 { 54 LL m = maxn; // 计算 f[m] 55 LL c = P/m; // 计算 P/m 56 LL a = F[m-1]; // 存下 f[m-1] 用于矩阵快速幂 57 LL b = F[m-2]; // 存下 f[m-2] 用于矩阵快速幂 58 LL num; // 代表 P/n == c 的n的数量 59 if(c != 0) // 如果 c == 0 我们就可以直接计算了 60 { 61 num = P/c - m + 1; // 计算这之间的数量 62 // 我们本次计算可以算到f[m+num-1],这就要求n+num-1 < n 63 // 我们要最后一次矩阵快速幂刚好能直接算到第n项 64 while(m + num <= n) 65 { 66 LL ta, tb; 67 ta = quick_pow(a, b, c, num); 68 if(num == 1) 69 tb = a; 70 else 71 tb = quick_pow(a, b, c, num-1); 72 m += num; 73 a = ta; // 更新目前的f[m-1] 74 b = tb; // 更新目前的f[m-2] 75 c = P/m; 76 if(c == 0) break; 77 num = P/c - m + 1; 78 } 79 } 80 num = n - m + 1; 81 LL ans = quick_pow(a, b, c, num); 82 printf("%lld\n", ans); 83 } 84 } 85 return 0; 86 }