The so-called matrix multiplication, is a new technique of learning when testing
Is literally understandable, using the multiplication idea to get the matrix we need
The theoretical basis is that the matrix satisfies the binding law and the distribution rate
UVa 11149
Bare topic, given matrix T, to find the matrix of t^1+......+t^n
We all know that using multiplication we can easily find the matrix of T^i (I=2^K), the time complexity is O (M^3LOGN)
We define a matrix of f (k) =t^1+......+t^ (2^K), which defines G (k) =t^ (2^k)
Not hard to find F (k+1) =f (k) +f (k) *g (k), G (k+1) =g (k) *g (k)
We then decompose N in a way that is like a fast power, and when the K bit is 1 we calculate the contribution of F (k) and add the answer
Time complexity O (M^3LOGN), slightly larger constant
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include < algorithm>using namespace Std;const int mod=10;int n,k;struct matrix{int a[42][42];void Clear () {memset (a,0,sizeof (A ));} void print () {for (int. i=1;i<=n;++i) {for (int j=1;j<=n;++j) {printf ("%d", a[i][j]), if (j==n) printf ("\ n"); else printf ("");}} printf ("\ n");}} A,b,c,i,ans,base; Matrix operator * (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=1;i<=n;++i) {for (int. j=1;j<=n;++j) {for (int k=1;k<=n;++k) {c.a[i][j]=c.a[i][j]+a.a[i][k ]*B.A[K][J];} C.a[i][j]%=mod;}} return C;} Matrix operator + (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int. i=1;i<=n;++i) {for (int j=1;j<=n;++j) {c.a[i][j]=a.a[i][j]+b.a[i][j];if (C.a[i][j]>=mod) C.a[i][j]-=mod;}} return C;} void Solve (int p) {b=a; C=a;ans.clear (); Base=i;while (p) {if (p&1) {ans=ans+b*base;base=base*c;} B=b+b*c; C=c*c;p>>=1;} return;} int main () {while (scanf ("%d%d", &n,&k) ==2) {if (!n) break;for (int i=1;i<=n;++i) {for (int j=1;j<=n;++j) {scanf ("%d", &a.a[i][j]); A.a[i][j]%=mod;}} I.clear (); for (int i=1;i<=n;++i) i.a[i][i]=1; Solve (k); Ans.print ();} return 0;}
5.25 Exam Questions T1
We also ask a^0+......+a^ (n-1)
At the time, my approach was to use geometric series summation and matrix inversion to make a mess.
Actually that topic can also write matrix multiply water past
#include <cstdio> #include <iostream> #include <algorithm> #include <cstdlib> #include < Cstring>using namespace Std; typedef long LONG Ll;const int mod=1e9+7;int t,n,k;struct matrix{LL a[2][2]; void Clear () {memset (a,0,sizeof (a));}} A,b,c,base,ans,i,ans; Matrix operator * (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=0;i<2;++i) {for (int. j=0;j<2;++j) {for (int k=0;k<2;++k) {c.a[i][j]=c.a[ I][j]+a.a[i][k]*b.a[k][j]%mod; if (c.a[i][j]>=mod) C.a[i][j]-=mod; }}}return C;} Matrix operator + (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int. i=0;i<2;++i) {for (int j=0;j<2;++j) {c.a[i][j]=a.a[i][j]+b.a[i][j]; if (c.a[i][j]>=mod) C.a[i][j]-=mod; }}return C;} void Solve (int p) {b=a; C=a;base=i;ans=i; while (p) {if (p&1) {ans=ans+b*base; Base=base*c; } B=b+b*c; c=c*c;p>>=1; }return;} Matrix Pow_mod (Matrix V,int p) {matrix tmp=i; while (p) {if (p&1) tmp=tmp*v; v=v*v;p>>=1; }return tmp;} int main () {scanf ("%d", &t); A.a[1][0]=a.a[0][1]=a.a[1][1]=1; I.a[0][0]=i.a[1][1]=1; while (t--) {scanf ("%d%d", &n,&k); if (n==1) {printf ("1\n"); continue;} n--; Solve (n); Ans=pow_mod (ANS,K); Ans.clear (); Ans.a[0][1]=1; Ans=ans*ans; printf ("%lld\n", ans.a[0][1]); }return 0;}
Bzoj Jiejie's female friend
This topic in Bzoj double experience Qaq, there is also a graph.
First we write out a n*k matrix, and then we write in the k*n matrix.
A lump in the title is obviously a linear combination of a bunch of vectors, so a matrix description can be used to get
Adjacency Matrix G=out*in, then the matrix of the number of paths that happen to be D is g^d
That is (out*in) ^d, we find that out*in gets the matrix of n*n, and In*out gets the matrix of k*k.
N<=1000,k<=20, so using the binding law, we can Bashi out* (in*out) ^ (d-1) *in
And then because the sum of requirements <=d, define T=in*out
out* (t^1+t^2+......+t^ (d-1)) can be obtained according to the distribution rate *in
The middle part uses the matrix multiplication to be able, finally pay attention to judge U==v
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include < Cstdlib>using namespace Std; typedef long LONG Ll;const int mod=1e9+7;int n,m,k,u,v,d; LL out[1010][22],in[22][1010]; ll Tmp[1010][22];struct matrix{ll a[22][22]; void Clear () {memset (a,0,sizeof (a));}} A,b,c,i,base,ans; void Read (LL &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar (); Num%=mod;} Matrix operator * (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=1;i<=k;++i) {for (int. j=1;j<=k;++j) {for (int k=1;k<=k;++k) {c.a[i][j]=c . A[i][j]+a.a[i][k]*b.a[k][j]%mod; if (c.a[i][j]>=mod) C.a[i][j]-=mod; }}}return C;} Matrix operator + (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=1;i<=k;++i) {for (int j=1;j<=k;++j) {c.a[i][j]=a.A[I][J]+B.A[I][J]; if (c.a[i][j]>=mod) C.a[i][j]-=mod; }}return C;} void Get_ans (int p) {b=a; C=a;ans=i;base=i; while (p) {if (p&1) {ans=ans+b*base; Base=base*c; } b=b+b*c; c=c*c;p>>=1; }return;} int main () {scanf ("%d%d", &n,&k); for (int i=1;i<=n;++i) {for (int j=1;j<=k;++j) read (out[i][j]); for (int j=1;j<=k;++j) read (In[j][i]); } for (int i=1;i<=k;++i) {for (int. j=1;j<=k;++j) {for (int k=1;k<=n;++k) {A.a[i] [J]=a.a[i][j]+in[i][k]*out[k][j]%mod; if (a.a[i][j]>=mod) A.a[i][j]-=mod; }}} for (int i=1;i<=k;++i) i.a[i][i]=1; scanf ("%d", &m); while (m--) {scanf ("%d%d%d", &u,&v,&d); if (d==0) {printf ("%d\n", (u==v?1:0)); continue;} d--; Get_ans (d); for (int i=1;i<=n;++i) {for (int j=1;j<=k;++j) {tmp[i][j]=0; for (int k=1;k<=k;++k) {tmp[i][j]=tmp[i][j]+out[i][k]*ans.a[k][j]%mod; if (tmp[i][j]>=mod) Tmp[i][j]-=mod; }}} LL s=0; for (int i=1;i<=k;++i) {s=s+tmp[u][i]*in[i][v]%mod; if (s>=mod) S-=mod; } if (u==v) s++; if (s>=mod) S-=mod; printf ("%lld\n", S); }return 0;}
Bzoj Path in Forest
The title translates to Sigma (i^2*t^i).
First of all, if there is no i^2 we will do, we may as well first consider the i*t^i situation
Define a (i) =t^i,b (i) =i*t^i
Not hard to find B (i) = (i-j) *t^i+j*t^i = ((i-j) *t^ (i-j) *t^j) + (j*t^j*t^ (i-j))
That is, b (i) = B (I-j) *a (j) + B (j) *a (I-J)
So we define C (i) =i^2*t^i
The same reasoning can be obtained
C (i) = C (i-j) *a (j) + C (j) *a (I-j) +2*b (j) *b (I-J)
And we're asking Sigma to do it with a matrix multiplier.
Accidentally wrote Ik*kj ij*jk for one hours Qaq
#include <cstdio> #include <cstring> #include <cstdlib> #include <iostream> #include < Algorithm>using namespace Std; typedef long LONG ll;int n,m,k,q,u,v;const int mod=1e9+7;struct matrix{LL a[110][110]; LL b[110][110]; LL c[110][110]; void Clear () {memset (a,0,sizeof (a)); Memset (b,0,sizeof (b)); Memset (C,0,sizeof (c)); } void Print () {for (int. i=1;i<=n;++i) {for (int j=1;j<=n;++j) {printf ("%lld", a[i ][J]); }printf ("\ n"); }printf ("\ n"); for (int i=1;i<=n;++i) {for (int j=1;j<=n;++j) {printf ("%lld", B[i][j]); }printf ("\ n"); }printf ("\ n"); for (int i=1;i<=n;++i) {for (int j=1;j<=n;++j) {printf ("%lld", C[i][j]); }printf ("\ n"); }printf ("\ n"); }}g,a,b,ans,base; Matrix operator * (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=1;i<=n;++i) {for (int j=1;j<=n;++j) {for (int k=1;k<=n;++k) {c.a[i][j]=c.a[i][j]+a.c[i][k]*b.a[ K][J]+A.A[I][K]*B.C[K][J]+2LL*A.B[I][K]*B.B[K][J]; C.a[i][j]%=mod; C.B[I][J]=C.B[I][J]+A.C[I][K]*B.B[K][J]+A.B[I][K]*B.C[K][J]; C.b[i][j]%=mod; C.C[I][J]=C.C[I][J]+A.C[I][K]*B.C[K][J]; C.c[i][j]%=mod; }}}return C;} Matrix operator + (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int. i=1;i<=n;++i) {for (int j=1;j<=n;++j) {c.c[i][j]=a.c[i][j]+b.c[i][j]; if (c.c[i][j]>=mod) C.c[i][j]-=mod; C.B[I][J]=A.B[I][J]+B.B[I][J]; if (c.b[i][j]>=mod) C.b[i][j]-=mod; C.A[I][J]=A.A[I][J]+B.A[I][J]; if (c.a[i][j]>=mod) C.a[i][j]-=mod; }}return C;} void Solve (int p) {for (int i=1;i<=n;++i) ans.c[i][i]=1; for (int i=1;i<=n;++i) base.c[i][i]=1; a=g; b=g; while (p) { if (p&1) {ans=ans+a*base; Base=base*b; } a=a+a*b; b=b*b;p>>=1; } return; int main () {scanf ("%d%d%d%d", &n,&m,&k,&q); for (int i=1;i<=m;++i) {scanf ("%d%d", &u,&v); g.a[u][v]++; g.b[u][v]++; g.c[u][v]++; } Solve (k); while (q--) {scanf ("%d%d", &u,&v); printf ("%d\n", Ans.a[u][v]); } return 0;}
Bzoj 4386
Because Benquan only three-way, so you can make each point into 3 points, so that the edge is 1, the practice with Scoi lost similar
After we consider the two-point answer, we can use matrix multiplication to determine if there are K
So Time complexity O ((3*n) ^3log^2k) will obviously t
First of all, for the convenience of statistics, we can use virtual nodes to connect to each point, and then this virtual point with a self-loop
So because of the existence of the self-ring we do not need to multiply the matrix, the direct rapid power can be
It's not hard to find that we've done some repetitive work every two minutes, and we can consider using multiplication
Preprocess out g^ (2^k), and then try adding from large to small to see if the number of scenarios is >=k
So the time complexity is less than a log
Notice that a long long may be blown out during matrix multiplication.
But we only need to compare with the size of K can be, explode long long is obviously larger than K, so with 1 to indicate this situation can be
Forget to write 1ll<<l result T's Nest at a loss
Notice that the upper bound of the answer is 3*k, and the limit is that the two points have a length of 3 on each side.
#include <cstdio> #include <cstring> #include <iostream> #include <cstdlib> #include < Algorithm>using namespace Std; typedef long Long Ll;int n,m,u,v,w,n,l; ll K,ans;int idx[42][3];int deg[122];struct matrix{LL a[122][122]; void Clear () {memset (a,0,sizeof (a));}} G,c,b,a[72];void read (int &num) {Num=0;char Ch=getchar (); while (ch< '! ') Ch=getchar (); while (ch>= ' 0 ' &&ch<= ' 9 ') num=num*10+ch-' 0 ', Ch=getchar ();} Matrix operator * (const matrix &a,const matrix &b) {matrix C; C.clear (); for (int i=0;i<=n;++i) {for (int. j=0;j<=n;++j) {for (int k=0;k<=n;++k) {if (a.a[i][k ]==-1| | B.a[k][j]==-1) {c.a[i][j]=-1;break;} if (a.a[i][k]==0| | b.a[k][j]==0) continue; if (A.a[i][k]>k/b.a[k][j]) {c.a[i][j]=-1;break;} C.A[I][J]+=A.A[I][K]*B.A[K][J]; if (c.a[i][j]>k) {c.a[i][j]=-1;break;} }}}return C;} BOOL Judge () {LL tot=0; FoR (int i=0;i<=n;++i) {if (!deg[i]) continue; if (b.a[0][i]==-1) return false; if (B.a[0][i]>k/deg[i]) return false; Tot+=b.a[0][i]*deg[i]; if (tot>=k) return false; }return true;} int main () {read (n); read (m); scanf ("%lld", &k); for (int i=1;i<=n;++i) {for (int j=0;j<3;++j) idx[i][j]=++n; } for (int i=1;i<=n;++i) {for (int j=1;j<3;++j) {u=idx[i][j-1];v=idx[i][j]; g.a[u][v]++; }g.a[0][idx[i][0]]++; }g.a[0][0]++; for (int i=1;i<=m;++i) {read (u); Read (v); Read (w);--w; g.a[idx[u][w]][idx[v][0]]++; deg[idx[u][w]]++; } for (l=0; (1ll<<l) <=K*3; l++); A[0]=g;ans=1; for (int i=1;i<l;++i) a[i]=a[i-1]*a[i-1]; for (int i=0;i<=n;++i) c.a[i][i]=1; for (int i=l-1;i>=0;--i) {b=c*a[i]; if (judge ()) {c=b; ans+= (1ll<<i); }} if (ans>k*3) printf (" -1\n"); else printf ("%lld\n", ans); return 0;}
Multiplication is a kind of thought, using any natural number can be written into Logn binary
If each contribution to the answer can be calculated independently, then we multiply the pre-processing of each bit and then merge it.
It can also be used for the conversion of two points, and to find a way of K-size
Common multiplication has a fast power, lca,rmq, matrix multiplication, etc.
The complexity of time is log.
Matrix Multiplication Learning Summary