『算法-ACM 竞赛-数学-数论』HDU - 6395 Let us define a sequence as below 分段矩阵快速幂
Your job is simple, for each task, you should output Fn module 109+7.
Input
The first line has only one integer T, indicates the number of tasks.
Then, for the next T lines, each line consists of 6 integers, A , B, C, D, P, n.
1≤T≤200≤A,B,C,D≤1091≤P,n≤109
Output
36
24
Sample Input
2
3 3 2 1 3 5
3 2 2 2 1 4
Sample Output
36
24
首先处理递推式这里,因为直接递推会超时,我们考虑矩阵快速幂,然后看题,有三个未知量,我们构造 3*3 的矩阵,然后因为还有一个数论分块,不能直接使用矩阵快速幂,应该相等的位置使用矩阵快速幂,然后完事了
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
| #include<bits/stdc++.h> using namespace std; typedef long long ll; const int mod = 1e9+7; int a, b, c, d, p, n, t;
struct mat{ int m[3][3]; mat(){ memset(m, 0, sizeof(mat)); } friend mat operator*(mat a, mat b){ mat c; for(int i=0; i<3; i++){ for(int j=0; j<3; j++){ ll t = 0; for(int k=0; k<3; k++){ t += (ll)a.m[i][k]*b.m[k][j]; } c.m[i][j] = t%mod; } } return c; } }I;
mat pow_mat(mat a, int b){ mat c = I; while(b){ if(b&1){ c = c*a; } a = a*a; b >>= 1; } return c; }
int main(){ I.m[0][0] = I.m[1][1] = I.m[2][2] = 1; scanf("%d", &t); while(t--){ scanf("%d%d%d%d%d%d", &a, &b, &c, &d, &p, &n); if(n == 1){ printf("%d\n", a); continue; } mat f; f.m[0][0] = d; f.m[0][1] = c; f.m[1][0] = 1; f.m[2][2] = 1; int flag = 0; for(int i=3; i<=n;){ if(p/i == 0){ mat w = f; w = pow_mat(w, n-i+1); ll ans = w.m[0][0]*(ll)b%mod + w.m[0][1]*(ll)a + w.m[0][2]%mod; ans %= mod; printf("%lld\n", ans); flag = 1; break; } int j = min(n, p/(p/i)); mat w = f; w.m[0][2] = p/i; w = pow_mat(w, j-i+1); ll tmp1 = (w.m[1][0]*(ll)b + w.m[1][1]*(ll)a + w.m[1][2]) % mod; ll tmp2 = (w.m[0][0]*(ll)b + w.m[0][1]*(ll)a + w.m[0][2]) % mod; a = tmp1; b = tmp2; i = j+1; } if(!flag) printf("%d\n", b); }
}
|