例题1: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Problem Description A为一个方阵,则Tr A表示A的迹(就是主对角线上各项的和),现要求Tr(A^k)%9973。 Input 数据的第一行是一个T,表示有T组数据。 每组数据的第一行有n(2 <= n <= 10)和k(2 <= k < 10^9)两个数据。接下来有n行,每行有n个数据,每个数据的范围是[0,9],表示方阵A的内容。 Output 对应每组数据,输出Tr(A^k)%9973。 输入样例 2 2 2 1 0 0 1 3 99999999 1 2 3 4 5 6 7 8 9 输出样例 2 2686
源码: 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 #include <bits/stdc++.h> using namespace std;long long a[11 ][11 ];const int mod=9973 ;void mul (long long (*a1)[11 ],long long (*a2)[11 ],int k) { long long remain[11 ][11 ]={0 } ; for (int i=1 ;i<=k;i++){ for (int j=1 ;j<=k;j++){ for (int z=1 ;z<=k;z++){ remain[i][j]+=(a1[i][z]*a2[z][j])%mod; } } } for (int i=1 ;i<=k;i++){ for (int j=1 ;j<=k;j++){ a1[i][j]=remain[i][j]; } } } void quick_mi (int k,int len) { long long remain[11 ][11 ]={0 }; for (int i=1 ;i<=len;i++){ remain[i][i]=1 ; } while (k){ if (k&1 )mul (remain,a,len); mul (a,a,len); k>>=1 ; } for (int i=1 ;i<=len;i++){ for (int j=1 ;j<=len;j++){ a[i][j]=remain[i][j]; } } } int main () { int t=0 ; scanf ("%d" ,&t); while (t--){ int n,k,ans=0 ; scanf ("%d%d" ,&n,&k); for (int i=1 ;i<=n;i++){ for (int j=1 ;j<=n;j++){ scanf ("%d" ,&a[i][j]); } } quick_mi (k,n); for (int i=1 ;i<=n;i++){ ans+=a[i][i]; if (ans>=mod){ ans%=mod; } } printf ("%d\n" ,ans); } return 0 ; }
这道题还比较基础,仅仅考验了矩阵运算和快速幂的部分,核心的将题目递推公式推出然后矩阵乘法化还没有考察到,但接下来的第二题便有所体现了。
例题2: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 Problem Description Everybody knows Fibonacci numbers, now we are talking about the Tribonacci numbers: T[0] = T[1] = T[2] = 1; T[n] = T[n - 1] + T[n - 2] + T[n - 3] (n >= 3) Given a and b, you are asked to calculate the sum from the ath Fibonacci number to the bth Fibonacci number, mod 1,000,000,007, that is (T[a] + T[a + 1] + … + T[b]) % 1,000,000,007. Input There are multiple cases (no more than 100). Each case contain two non-negative integers a b(a <= b and a, b < 1,000,000,000) Output For each case, output the sum % 1,000,000,007. 输入样例 0 2 0 5 输出样例 3 20
题目大意是我们现在重新定义一个数列规律,求第a项到第b项之和。
源码: 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 80 81 82 83 84 85 86 87 88 89 90 #include <bits/stdc++.h> using namespace std;const long long mod=1e9 +7 ;long long b[5 ][5 ];long long f[5 ]={0 ,3 ,1 ,1 ,1 };int a,b1;void init_mat () { for (int i=1 ;i<=4 ;i++){ for (int j=1 ;j<=4 ;j++){ if (i==1 ){ b[i][j]=1 ; } else if (i==2 ){ if (j==1 ){ b[i][j]=0 ; } else { b[i][j]=1 ; } } else { if (i-1 ==j){ b[i][j]=1 ; } else { b[i][j]=0 ; } } } } } void mul (long long (*a)[5 ],long long (*a1)[5 ]) { long long remain[5 ][5 ]={0 }; for (int i=1 ;i<=4 ;i++){ for (int j=1 ;j<=4 ;j++){ for (int z=1 ;z<=4 ;z++){ remain[i][j]=(remain[i][j]+a[i][z]*a1[z][j])%mod; } } } for (int i=1 ;i<=4 ;i++){ for (int j=1 ;j<=4 ;j++){ a[i][j]=remain[i][j]; } } } void quick_mi (int k) { long long remain[5 ][5 ]={0 }; for (int i=1 ;i<=4 ;i++){ remain[i][i]=1 ; } while (k){ if (k&1 )mul (remain,b); mul (b,b); k>>=1 ; } for (int i=1 ;i<=4 ;i++){ for (int j=1 ;j<=4 ;j++){ b[i][j]=remain[i][j]; } } } int count (int k) { if (k<0 ){ return 0 ; } else if (k<3 ){ return k+1 ; } else { long long ans=0 ; quick_mi (k-2 ); for (int i=1 ;i<=4 ;i++){ ans+=b[1 ][i]*f[i]; if (ans>=mod)ans%=mod; } return ans; } } int main () { while (scanf ("%d%d" ,&a,&b1)==2 ){ init_mat (); int ans1=count (a-1 ); init_mat (); int ans2=count (b1); printf ("%d\n" ,(ans2-ans1+mod)%mod); } return 0 ; }
这道题虽然给出了我们到第几项的规律,但是需要求的是sum,所以我们还需要推出前缀和的原公式,然后再进行矩阵快速幂。
例题3: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 Problem Description As we all known , the Fibonacci series : F(0) = 1, F(1) = 1, F(N) = F(N - 1) + F(N - 2) (N >= 2).Now we define another kind of Fibonacci : A(0) = 1 , A(1) = 1 , A(N) = X A(N - 1) + Y A(N - 2) (N >= 2).And we want to Calculate S(N) , S(N) = A(0)^2 +A(1)^2+……+A(n)^2. Input There are several test cases. Each test case will contain three integers , N, X , Y . N : 2<= N <= 2^31 – 1 X : 2<= X <= 2^31– 1 Y : 2<= Y <= 2^31 – 1 Output For each test case , output the answer of S(n).If the answer is too big , divide it by 10007 and give me the reminder. 输入样例 2 1 1 3 2 3 输出样例 6 196
源码: 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 80 81 82 83 84 85 86 87 88 89 90 91 92 #include <bits/stdc++.h> using namespace std;const int mod=10007 ;long long n,x,y;long long f[4 ]={2 ,1 ,1 ,1 };long long b[4 ][4 ]={0 };void init_mat () { for (int i=0 ;i<4 ;i++){ for (int j=0 ;j<4 ;j++){ if (i==0 ){ b[i][0 ]=1 ; b[i][1 ]=x*x%mod; b[i][2 ]=2 *x*y%mod; b[i][3 ]=y*y%mod; } else if (i==1 ){ b[i][0 ]=0 ; b[i][1 ]=x*x%mod; b[i][2 ]=2 *x*y%mod; b[i][3 ]=y*y%mod; } else if (i==2 ){ b[i][0 ]=0 ; b[i][1 ]=x; b[i][2 ]=y; b[i][3 ]=0 ; } else { b[i][0 ]=0 ; b[i][1 ]=1 ; b[i][2 ]=0 ; b[i][3 ]=0 ; } } } } void mul (long long (*a)[4 ],long long (*a1)[4 ]) { long long remain[4 ][4 ]={0 }; for (int i=0 ;i<4 ;i++){ for (int j=0 ;j<4 ;j++){ for (int z=0 ;z<4 ;z++){ remain[i][j]=(remain[i][j]+a[i][z]*a1[z][j])%mod; } } } for (int i=0 ;i<4 ;i++){ for (int j=0 ;j<4 ;j++){ a[i][j]=remain[i][j]; } } } void quick_mi (int k) { long long remain[4 ][4 ]={0 }; for (int i=0 ;i<4 ;i++){ remain[i][i]=1 ; } while (k){ if (k&1 )mul (remain,b); mul (b,b); k>>=1 ; } for (int i=0 ;i<4 ;i++){ for (int j=0 ;j<4 ;j++){ b[i][j]=remain[i][j]; } } } int main () { while (scanf ("%lld%lld%lld" ,&n,&x,&y)==3 ){ if (x>=mod){ x%=mod; } if (y>=mod){ y%=mod; } if (n<2 ){ if (n==0 )printf ("1\n" ); else if (n==1 )printf ("2\n" ); } init_mat (); quick_mi (n-1 ); long long ans=0 ; for (int i=0 ;i<4 ;i++){ ans+=f[i]*b[0 ][i]; if (ans>=mod)ans%=mod; } printf ("%d\n" ,ans); } return 0 ; }
这篇博客仅仅还是一篇草稿,温故而知新,还需要后期的复习后的感想,才算发挥出来这篇博客应有的作用。