[矩阵乘法/快速幂专题]Arc of Dream,Recursive sequence,233 Matrix,Training little cats
矩陣快速冪習題
- 復習矩陣乘法及快速冪模板
- 乘法模板
- 快速冪模板
- T1:Arc of Dream
- 題目
- 題解
- code
- T2:Recursive sequence
- 題目
- 題解
- code
- T3:233 Matrix
- 題目
- 題解
- code
- T4:Training little cats
- 題目
- 題解
- code
做題的時候后悔沒有保存過模板,還到處去找自己曾經寫過的模板,然并卵,還是重新寫了一遍,其實如果知道原理,就不用背模板了
每次復習的時候打完就覺得自己記住了,然而
復習矩陣乘法及快速冪模板
具體怎么乘的,移步百度百科
乘法模板
struct Matrix {int n, m;LL c[MAXN][MAXN];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) const {Matrix res;res.n = n;res.m = a.m;for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= a.m;j ++ )for ( int k = 1;k <= m;k ++ )res.c[i][j] = ( res.c[i][j] + c[i][k] * a.c[k][j] % mod ) % mod; return res;} };快速冪模板
Matrix qkpow ( Matrix &a, LL b ) {Matrix res;res.n = a.n;res.m = a.m;for ( int i = 1;i <= res.n;i ++ )res.c[i][i] = 1;while ( b ) {if ( b & 1 )res = res * a;a = a * a;b >>= 1;}return res; }T1:Arc of Dream
題目
夢想之弧是由以下函數定義的曲線:
∑i=0n?1aibi\sum_{i=0}^{n-1}a_ib_ii=0∑n?1?ai?bi?
其中
a0=A0a_0 = A0a0?=A0
ai=ai?1?AX+AYa_i = a_{i-1} * AX + AYai?=ai?1??AX+AY
b0=B0b_0 = B_0b0?=B0?
bi=bi?1?BX+BYb_i = b_{i-1} * BX + BYbi?=bi?1??BX+BY
AoD(N)取1,000,000,007模的值是多少?
輸入項
有多個測試用例。處理到文件末尾。
每個測試用例包含以下7個非負整數:
N
A0 AX AY
B0 BX BY
N不大于101810^{18}1018,所有其他整數不大于2×1092×10^92×109
輸出量
對于每個測試用例,以模1,000,000,007輸出AoD(N)。
樣本輸入
1
1 2 3
4 5 6
2
1 2 3
4 5 6
3
1 2 3
4 5 6
樣本輸出
4
134
1902
題解
首先最后快速冪后肯定要有求和的答案,所以要占一位,接著把轉移要用到的AX,AY...AX,AY...AX,AY...也甩進加速矩陣中,然后發現轉移后的ai,bia_i,b_iai?,bi?還要加上某一些常數,所以我們還要給一位常數項,我們可以把初始矩陣定義常數項為111,在加速矩陣中再乘上常數
初始矩陣
[0(當前求和答案),a0?b0,a0,b0,1(常數項)]\begin{bmatrix} 0(當前求和答案),a_0*b_0,a_0,b_0,1(常數項) \end{bmatrix} [0(當前求和答案),a0??b0?,a0?,b0?,1(常數項)?]
考慮如何轉移,寫出加速矩陣
[100001AX?AY0000AXAX000BX0BX00AY?BYAYBY1]\begin{bmatrix} 1&0&0&0&0\\ 1&AX*AY&0&0&0\\ 0&AX&AX&0&0\\ 0&BX&0&BX&0\\ 0&AY*BY&AY&BY&1\\ \end{bmatrix} ???????11000?0AX?AYAXBXAY?BY?00AX0AY?000BXBY?00001????????
這一題我仔細地推一遍,后面就不仔細推了,可能直接給加速矩陣和初始矩陣
code
#include <cstdio> #include <cstring> #define LL long long #define mod 1000000007 #define MAXN 10 LL N, A0, Ax, Ay, B0, Bx, By; struct Matrix {int n, m;LL c[MAXN][MAXN];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) const {Matrix res;res.n = n;res.m = a.m;for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= a.m;j ++ )for ( int k = 1;k <= m;k ++ )res.c[i][j] = ( res.c[i][j] + c[i][k] * a.c[k][j] % mod ) % mod; return res;}void read () {for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= m;j ++ )scanf ( "%lld", &c[i][j] );}void print () {printf ( "%lld\n", c[1][1] );} }A;Matrix qkpow ( Matrix &a, LL b ) {Matrix res;res.n = a.n;res.m = a.m;for ( int i = 1;i <= res.n;i ++ )res.c[i][i] = 1;while ( b ) {if ( b & 1 )res = res * a;a = a * a;b >>= 1;}return res; }int main() {while ( ~ scanf ( "%lld", &N ) ) {scanf ( "%lld %lld %lld %lld %lld %lld", &A0, &Ax, &Ay, &B0, &Bx, &By );Matrix res;res.n = res.m = 5;res.c[1][1] = res.c[2][1] = res.c[5][5] = 1;res.c[2][2] = Ax * Bx % mod;res.c[3][2] = Ax * By % mod;res.c[3][3] = Ax % mod;res.c[4][2] = Bx * Ay % mod;res.c[4][4] = Bx % mod;res.c[5][2] = Ay * By % mod;res.c[5][3] = Ay % mod;res.c[5][4] = By % mod;res = qkpow ( res, N );A.n = 1;A.m = 5;A.c[1][1] = 0;A.c[1][2] = A0 * B0 % mod;A.c[1][3] = A0 % mod;A.c[1][4] = B0 % mod;A.c[1][5] = 1;A = A * res;A.print();}return 0; }T2:Recursive sequence
題目
Farmer John likes to play mathematics games with his N cows. Recently, they are attracted by recursive sequences. In each turn, the cows would stand in a line, while John writes two positive numbers a and b on a blackboard. And then, the cows would say their identity number one by one. The first cow says the first number a and the second says the second number b. After that, the i-th cow says the sum of twice the (i-2)-th number, the (i-1)-th number, and i^4. Now, you need to write a program to calculate the number of the N-th cow in order to check if John’s cows can make it right.
Input
The first line of input contains an integer t, the number of test cases. t test cases follow.
Each case contains only one line with three numbers N, a and b where N,a,b<231N,a,b < 2^{31}N,a,b<231 as described above.
Output
For each test case, output the number of the N-th cow. This number might be very large, so you need to output it modulo 2147493647.
Sample Input
2
3 1 2
4 1 10
Sample Output
85
369
Hint
In the first case, the third number is 85=2?1十2十3485 = 2*1十2十3^485=2?1十2十34.
In the second case, the third number is 93=2?1十1?10十3493 = 2*1十1*10十3^493=2?1十1?10十34 and the fourth number is 369=2?10十93十44369 = 2 * 10 十 93 十 4^4369=2?10十93十44.
一句話題意
給定a,ba,ba,b分別為第一項和第二項求第n項,第i項等于2(i?2)+(i?1)+i42(i-2)+(i-1)+i^42(i?2)+(i?1)+i4
題解
2(i?1),(i?1)2(i-1),(i-1)2(i?1),(i?1)都很好轉移,但是i4i^4i4就有點難了,我們可以這樣處理
i4=(i?1+1)4i^4=(i-1+1)^4i4=(i?1+1)4,將i?1i-1i?1看作一個整體,這樣就運用二項式展開,用到楊輝三角1,4,6,4,11,4,6,4,11,4,6,4,1,但是這個時候又要知道i3,i2,i1,i0=1i^3,i^2,i^1,i^0=1i3,i2,i1,i0=1才能進行轉移,用同樣的方式處理它們,就可以進行轉移了
初始矩陣
a,b,21,22,23,24,1a,b,2^1,2^2,2^3,2^4,1a,b,21,22,23,24,1
加速矩陣(就不推了,直接給)
[0200000110000004123400601360040014001000100111111]\begin{bmatrix} 0&2&0&0&0&0&0\\ 1&1&0&0&0&0&0\\ 0&4&1&2&3&4&0\\ 0&6&0&1&3&6&0\\ 0&4&0&0&1&4&0\\ 0&1&0&0&0&1&0\\ 0&1&1&1&1&1&1\\ \end{bmatrix} ???????????0100000?2146411?0010001?0021001?0033101?0046411?0000001????????????
code
#include <cstdio> #include <cstring> #define mod 2147493647 #define LL long long #define maxn 10 int t; LL n, a, b;struct Matrix {int n, m;LL c[maxn][maxn];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) const {Matrix res;res.n = n;res.m = a.m;for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= a.m;j ++ )for ( int k = 1;k <= m;k ++ )res.c[i][j] = ( res.c[i][j] + c[i][k] * a.c[k][j] % mod ) % mod; return res;}void print() {printf ( "%lld\n", c[1][2] );} }A;Matrix qkpow ( Matrix a, LL b ) {Matrix ans;ans.n = ans.m = a.n;for ( int i = 1;i <= a.n;i ++ )ans.c[i][i] = 1;while ( b ) {if ( b & 1 )ans = ans * a;a = a * a;b >>= 1;}return ans; }int main() {scanf ( "%d", &t );while ( t -- ) {scanf ( "%lld %lld %lld", &n, &a, &b );if ( n == 1 )printf ( "%lld\n", a );if ( n == 2 )printf ( "%lld\n", b );Matrix tmp;tmp.n = tmp.m = 7;tmp.c[2][1] = tmp.c[2][2] = tmp.c[3][3] = tmp.c[4][4] = tmp.c[5][5] = tmp.c[6][2] = tmp.c[6][6] = tmp.c[7][2] = tmp.c[7][3] = tmp.c[7][4] = tmp.c[7][5] = tmp.c[7][6] = tmp.c[7][7] = 1;tmp.c[1][2] = tmp.c[3][4] = 2;tmp.c[3][5] = tmp.c[4][5] = 3;tmp.c[3][2] = tmp.c[3][6] = tmp.c[5][6] = tmp.c[5][2] = 4;tmp.c[4][2] = tmp.c[4][6] = 6;tmp = qkpow ( tmp, n - 2 );A.n = 1;A.m = 7;A.c[1][1] = a;A.c[1][2] = b;A.c[1][3] = 2;A.c[1][4] = 4;A.c[1][5] = 8;A.c[1][6] = 16;A.c[1][7] = 1;A = A * tmp;A.print();}return 0; }T3:233 Matrix
題目
In our daily life we often use 233 to express our feelings. Actually, we may say 2333, 23333, or 233333 … in the same meaning. And here is the question: Suppose we have a matrix called 233 matrix. In the first line, it would be 233, 2333, 23333… (it means a 0,1 = 233,a 0,2 = 2333,a 0,3 = 23333…) Besides, in 233 matrix, we got a i,j = a i-1,j +a i,j-1( i,j ≠ 0). Now you have known a 1,0,a 2,0,…,a n,0, could you tell me a n,m in the 233 matrix?
Input
There are multiple test cases. Please process till EOF.
For each case, the first line contains two postive integers n,m(n ≤ 10,m ≤ 10^9). The second line contains n integers, a 1,0,a 2,0,…,a n,0(0 ≤ a i,0 < 2 31).
Output
For each case, output a n,m mod 10000007.
Sample Input
1 1
1
2 2
0 0
3 7
23 47 16
Sample Output
234
2799
72937
Hint
題解
看圖↓:
我們可以考慮用對角線去處理,因為nnn很小,可以暴力算出第一根紅線之前所有點的值
然后畫出平移的一條線發現轉移規律,除了第一個點是直接由上一條線第一個點轉移,其余的點都是上一條線的對應點和上一個點的和,我們以第一條對角線為初始矩陣,那么進行mmm次轉移即可,用快速冪搞定
加速矩陣為:
[110...00011...00001...00......000...10000...11000...01]\begin{bmatrix} 1&1&0&...&0&0\\ 0&1&1&...&0&0\\ 0&0&1&...&0&0\\ .&.&.&.&.&.\\ 0&0&0&...&1&0\\ 0&0&0&...&1&1\\ 0&0&0&...&0&1 \end{bmatrix} ???????????100.000?110.000?011.000?...................?000.110?000.011????????????
code
#include <cstdio> #include <cstring> #define mod 10000007 #define LL long long #define maxn 15 LL n, m; LL a[maxn][maxn];struct Matrix {int n, m;LL c[maxn][maxn];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) const {Matrix res;res.n = n;res.m = a.m;for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= a.m;j ++ )for ( int k = 1;k <= m;k ++ )res.c[i][j] = ( res.c[i][j] + c[i][k] * a.c[k][j] % mod ) % mod; return res;}void print() {printf ( "%lld\n", c[1][m - 1] );} }A;Matrix qkpow ( Matrix a, LL b ) {Matrix ans;ans.n = ans.m = a.n;for ( int i = 1;i <= a.n;i ++ )ans.c[i][i] = 1;while ( b ) {if ( b & 1 )ans = ans * a;a = a * a;b >>= 1;}return ans; }int main() {while ( ~ scanf ( "%lld %lld", &n, &m ) ) {for ( int i = 1;i <= n;i ++ )scanf ( "%lld", &a[i][0] );a[0][1] = 233;for ( int i = 2;i <= n;i ++ )a[0][i] = ( a[0][i - 1] * 10 % mod + 3 ) % mod;for ( int i = 1;i <= n;i ++ )for ( int j = 1;j <= n - i;j ++ )a[i][j] = ( a[i - 1][j] + a[i][j - 1] ) % mod;A.n = 1;A.m = n + 2;for ( int i = 1;i <= n + 1;i ++ )A.c[1][i] = a[i - 1][n - i + 1];A.c[1][n + 2] = 3;Matrix res;res.n = res.m = n + 2;res.c[1][1] = 10;res.c[n + 2][1] = res.c[n + 2][n + 2] = 1;for ( int i = 2;i <= n + 1;i ++ )res.c[i][i] = res.c[i - 1][i] = 1;res = qkpow ( res, m );A = A * res;A.print();}return 0; }T4:Training little cats
題目
Facer’s pet cat just gave birth to a brood of little cats. Having considered the health of those lovely cats, Facer decides to make the cats to do some exercises. Facer has well designed a set of moves for his cats. He is now asking you to supervise the cats to do his exercises. Facer’s great exercise for cats contains three different moves:
g i : Let the ith cat take a peanut.
e i : Let the ith cat eat all peanuts it have.
s i j : Let the ith cat and jth cat exchange their peanuts.
All the cats perform a sequence of these moves and must repeat it m times! Poor cats! Only Facer can come up with such embarrassing idea.
You have to determine the final number of peanuts each cat have, and directly give them the exact quantity in order to save them.
Input
The input file consists of multiple test cases, ending with three zeroes “0 0 0”. For each test case, three integers n, m and k are given firstly, where n is the number of cats and k is the length of the move sequence. The following k lines describe the sequence.
(m≤1,000,000,000, n≤100, k≤100)
Output
For each test case, output n numbers in a single line, representing the numbers of peanuts the cats have.
Sample Input
3 1 6
g 1
g 2
g 2
s 1 2
g 3
e 2
0 0 0
Sample Output
2 0 1
題解
分三種情況,可以考慮多給加速矩陣提供一行常數項
ggg就直接+1+1+1
eee就將該只小貓的那一列全部清零
sss就直接swapswapswap交換兩列
最后直接快速冪即可,比較簡單
code
#include <cstdio> #include <cstring> #include <iostream> using namespace std; #define LL long long #define maxn 105struct Matrix {int n, m;LL c[maxn][maxn];Matrix () {memset ( c, 0, sizeof ( c ) );}Matrix operator * ( const Matrix &a ) {Matrix ans;ans.n = n;ans.m = a.m;for ( int i = 1;i <= n;i ++ )for ( int k = 1;k <= m;k ++ )if ( c[i][k] )for ( int j = 1;j <= a.m;j ++ )ans.c[i][j] += c[i][k] * a.c[k][j];return ans;}void print() {for ( int i = 1;i < m;i ++ )printf ( "%lld ", c[1][i] );printf ( "\n" );} }A;Matrix qkpow ( Matrix a, LL b ) {Matrix ans;ans.n = a.n;ans.m = a.m;for ( int i = 1;i <= ans.n;i ++ )ans.c[i][i] = 1;while ( b ) {if ( b & 1 )ans = ans * a;a = a * a;b >>= 1;}return ans; }int main() {int n, m, k, cat, Cat;char opt;while ( ~ scanf ( "%d %d %d", &n, &m, &k ) ) {if ( ! n && ! m && ! k )return 0;memset ( A.c, 0, sizeof ( A.c ) );A.n = 1;A.m = n + 1;A.c[1][n + 1] = 1;Matrix ans;ans.n = n + 1;ans.m = n + 1;for ( int i = 1;i <= ans.n;i ++ )ans.c[i][i] = 1;for ( int i = 1;i <= k;i ++ ) {getchar();scanf ( "%c %d", &opt, &cat );if ( opt == 'g' )ans.c[ans.m][cat] ++;else if ( opt == 'e' ) {for ( int j = 1;j <= ans.n;j ++ )ans.c[j][cat] = 0;} else {scanf ( "%d", &Cat );for ( int j = 1;j <= ans.n;j ++ )swap ( ans.c[j][cat], ans.c[j][Cat] );}}ans = qkpow ( ans, m );A = A * ans;A.print();}return 0; }有任何問題歡迎提出,byebye
總結
以上是生活随笔為你收集整理的[矩阵乘法/快速幂专题]Arc of Dream,Recursive sequence,233 Matrix,Training little cats的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 王者荣耀2020新区开服表 具体开服时间
- 下一篇: 春运开始时间2021年 2021春运的时