做了几个矩阵问题,总结一下。
矩阵是个很神奇的东西,有时候对于一个有规律的操作,需要执行很多次的时候,有时候可以构造矩阵很巧妙的解决。
另外对于递推式求解,可以通过构造矩阵巧妙解决。
经典的便是FIB数列,以及FIB数列的求和问题。
HDU 1575 Tr A
http://acm.hdu.edu.cn/showproblem.php?pid=1575
赤裸的矩阵快速幂乘
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 10
- #define inf 1<<29
- #define MOD 9973
- #define LL long long
- using namespace std;
- struct Matrix{
- int m[N][N];
- }init;
- int n,k;
- Matrix Mult(Matrix m1,Matrix m2){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1);
- m1=Mult(m1,m1);
- b>>=1;
- }
- return ans;
- }
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&n,&k);
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- scanf("%d",&init.m[i][j]);
- init=Pow(init,k);
- int ans=0;
- for(int i=0;i<n;i++)
- ans=(ans+init.m[i][i])%MOD;
- printf("%d\n",ans);
- }
- return 0;
- }
HDU 1588 Gauss Fibonacci
http://acm.hdu.edu.cn/showproblem.php?pid=1588
构造矩阵,通过矩阵乘法可以得到FIB数列的某一项,矩阵为{1,1,1,0}
其中这里要求的为
F(b)+F(k+b)+F(2*k+b)……
用矩阵表示即为A^b+A^(k+b)……,可以转化为A^b*(A^(0)+A^(k)……)
将K=A^k,即A^b*(K^0+K^1+K^2……),对于括号内部部分,有经典的二分解法,在Matrix67博客里面也有介绍
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 10
- using namespace std;
- struct Matrix{
- LL m[N][N];
- }init,unit;
- int MOD;
- Matrix Mult(Matrix m1,Matrix m2,int n=2){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n=2){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n=2){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;
- return ans;
- }
- Matrix slove(Matrix init,int k,int n=2){
- if(k==1)
- return init;
- Matrix temp=slove(init,k>>1,n);
- temp=Add(temp,Mult(temp,Pow(init,k>>1)));
- if(k&1)
- return Add(temp,Pow(init,k));
- else
- return temp;
- }
- int main(){
- int k,b,n;
- while(scanf("%d%d%d%d",&k,&b,&n,&MOD)!=EOF){
- init.m[0][0]=init.m[0][1]=init.m[1][0]=1;
- init.m[1][1]=0;
- unit.m[0][0]=unit.m[1][1]=1;
- unit.m[1][0]=unit.m[0][1]=0;
- Matrix t;
- t=Pow(init,b);
- init=Pow(init,k);
- //init.m[0][1]即第k项fib,为A^k
- init=Add(unit,slove(init,n-1)); //B=A^k, B^0+B^1+B^2……+B^n-1
- init=Mult(init,t);
- printf("%I64d\n",init.m[0][1]);
- }
- return 0;
- }
HDU 1757 A Simple Math Problem
http://acm.hdu.edu.cn/webcontest/contest_showproblem.php?cid=1432&pid=1001&ojid=0
经典的构造矩阵解决递推式问题
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 10
- #define inf 1<<29
- //#define MOD 9973
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- LL m[N][N];
- }init,unit;
- int MOD;
- Matrix Mult(Matrix m1,Matrix m2,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;
- return ans;
- }
- Matrix slove(Matrix init,int k,int n=10){
- if(k==1)
- return init;
- Matrix temp=slove(init,k>>1,n);
- temp=Add(temp,Mult(temp,Pow(init,k>>1)));
- if(k&1)
- return Add(temp,Pow(init,k));
- else
- return temp;
- }
- void debug(Matrix m1){
- for(int i=0;i<10;i++){
- for(int j=0;j<10;j++)
- printf("%d ",m1.m[i][j]);
- printf("\n");
- }
- }
- int main(){
- int k,b,n;
- int a[10];
- while(scanf("%d%d",&k,&MOD)!=EOF){
- for(int i=0;i<10;i++)
- scanf("%d",&a[i]);
- if(k<10)
- printf("%d\n",k);
- else{
- memset(init.m,0,sizeof(init.m));
- for(int i=0;i<10;i++)
- init.m[i][0]=a[i];
- for(int i=1;i<10;i++)
- init.m[i-1][i]=1;
- init=Pow(init,k-9);
- LL ans=0;
- for(int i=0;i<10;i++)
- ans=(ans+(9-i)*init.m[i][0])%MOD;
- printf("%I64d\n",ans);
- }
- }
- return 0;
- }
HDU 2157 How many ways??
http://acm.hdu.edu.cn/showproblem.php?pid=2157
又是一个经典的应用 ,在离散数学中有讲,可达矩阵的K次幂便是从i到j走K步能到达的方案数
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 25
- #define inf 1<<29
- #define MOD 1000
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- LL m[N][N];
- }init,unit;
- Matrix Mult(Matrix m1,Matrix m2,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=((LL)ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n=10){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=((LL)m1.m[i][j]+m2.m[i][j])%MOD;
- return ans;
- }
- Matrix slove(Matrix init,int k,int n=10){
- if(k==1)
- return init;
- Matrix temp=slove(init,k>>1,n);
- temp=Add(temp,Mult(temp,Pow(init,k>>1)));
- if(k&1)
- return Add(temp,Pow(init,k));
- else
- return temp;
- }
- void debug(Matrix m1){
- for(int i=0;i<10;i++){
- for(int j=0;j<10;j++)
- printf("%d ",m1.m[i][j]);
- printf("\n");
- }
- }
- int main(){
- int n,m;
- while(scanf("%d%d",&n,&m)!=EOF&&n+m){
- memset(init.m,0,sizeof(init.m));
- int u,v,q,k;
- while(m--){
- scanf("%d%d",&u,&v);
- init.m[u][v]=1;
- }
- scanf("%d",&q);
- while(q--){
- scanf("%d%d%d",&u,&v,&k);
- Matrix unit=Pow(init,k,n);
- printf("%d\n",unit.m[u][v]);
- }
- }
- return 0;
- }
http://poj.org/problem?id=3233
经典矩阵二分,A^1+A^2+A^3……A^n,如果n为偶数A^1+A^2……A^n/2+A^(n/2)*(A^1+A^2……A^n/2)如果是奇数,就在最后再加一项A^n,这样就可以递归二分下去。
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 35
- #define inf 1<<29
- //#define MOD 9973
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- int m[N][N];
- }init,unit;
- int MOD;
- Matrix Mult(Matrix m1,Matrix m2,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;
- return ans;
- }
- Matrix slove(Matrix init,int k,int n){
- if(k==1)
- return init;
- Matrix temp=slove(init,k>>1,n);
- temp=Add(temp,Mult(temp,Pow(init,k>>1,n),n),n);
- if(k&1)
- return Add(temp,Pow(init,k,n),n);
- else
- return temp;
- }
- void debug(Matrix m1,int n){
- for(int i=0;i<n;i++){
- printf("%d",m1.m[i][0]);
- for(int j=1;j<n;j++)
- printf(" %d",m1.m[i][j]);
- printf("\n");
- }
- }
- int main(){
- int k,b,n;
- while(scanf("%d%d%d",&n,&k,&MOD)!=EOF){
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- scanf("%d",&init.m[i][j]);
- init.m[i][j]%=MOD;
- }
- debug(slove(init,k,n),n);
- }
- return 0;
- }
ZOJ 3497 Mistwald
同样首先判断是否可达,如果K次不可达,则必然是False。如果K次只能到达目标点,则说明是实话,如果K次有多点可达,则说明是可能
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3497
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 30
- #define inf 1<<29
- //#define MOD 9973
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- int m[N][N];
- }init,unit;
- Matrix Mult(Matrix m1,Matrix m2,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j]);
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(m1.m[i][j]+m2.m[i][j]);
- return ans;
- }
- int main(){
- int t,c,r;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&r,&c);
- memset(init.m,0,sizeof(init.m));
- for(int i=0;i<r;i++){
- for(int j=0;j<c;j++){
- int x1,x2,x3,x4,y1,y2,y3,y4;
- getchar();
- scanf("((%d,%d),(%d,%d),(%d,%d),(%d,%d))",&x1,&y1,&x2,&y2,&x3,&y3,&x4,&y4);
- if(i==r-1&&j==c-1) continue;
- init.m[i*c+j][(x1-1)*c+y1-1]=1;
- init.m[i*c+j][(x2-1)*c+y2-1]=1;
- init.m[i*c+j][(x3-1)*c+y3-1]=1;
- init.m[i*c+j][(x4-1)*c+y4-1]=1;
- }
- }
- int q,k;
- // for(int i=0;i<r*c;i++)
- // init.m[i][i]=0;
- scanf("%d",&q);
- while(q--){
- scanf("%d",&k);
- Matrix tmp=Pow(init,k,r*c);
- if(tmp.m[0][r*c-1]==0){
- puts("False");
- continue;
- }
- int cnt=0;
- for(int i=0;i<r*c-1;i++)
- if(tmp.m[0][i])
- cnt++;
- if(!cnt)
- puts("True");
- else
- puts("Maybe");
- }
- puts("");
- }
- return 0;
- }
HDU 2807 The Shortest Path
http://acm.hdu.edu.cn/showproblem.php?pid=2807
没啥好说的,直接搞就行了。不过挺卡时间的,注意优化
- #include <cstdio>
- #include <iostream>
- #define NN 81
- #define inf 1<<29
- using namespace std;
- int n,m;
- int matrix[NN][NN][NN];
- int dis[NN][NN];
- void init(){
- for(int i=1;i<=n;i++)
- for (int j=1; j<=m; j++)
- for (int k=1; k<=m; k++)
- scanf("%d",&matrix[i][j][k]);
- }
- void get_dis(){
- int temp[NN][NN];
- for (int a=1; a<=n; a++)
- for (int b=1; b<=n; b++)
- dis[a][b]=inf;
- for (int a=1; a<=n; a++)
- for (int b=1; b<=n; b++) {
- if(a==b) continue;
- for (int i=1; i<=m; i++){
- for (int j=1; j<=m; j++){
- temp[i][j]=0;
- for (int k=1; k<=m; k++)
- temp[i][j]+=matrix[a][i][k]*matrix[b][k][j];
- }
- }
- for(int c=1; c<=n; c++){
- if(a==c||b==c) continue;
- int flag=1;
- for (int i=1; i<=m && flag; i++)
- for (int j=1; j<=m && flag; j++)
- if (temp[i][j]!=matrix[c][i][j]) flag=0;
- if (flag) dis[a][c]=1;
- }
- }
- }
- void Floyed(){
- for(int k=1;k<=n;k++)
- for(int i=1;i<=n;i++)
- for(int j=1;j<=n;j++){
- if (k==i || k==j || i==j) continue;
- if (dis[i][j]>dis[i][k]+dis[k][j])
- dis[i][j]=dis[i][k]+dis[k][j];
- }
- }
- void Query(){
- int t,x,y;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&x,&y);
- if (dis[x][y]>=inf)
- printf("Sorry\n");
- else
- printf("%d\n",dis[x][y]);
- }
- }
- int main(){
- while(scanf("%d%d",&n,&m)!=EOF&&n!=0&&m!=0){
- init();
- get_dis();
- Floyed();
- Query();
- }
- return 0;
- }
HDU 3483 A Very Simple Problem
http://acm.hdu.edu.cn/showproblem.php?pid=3483
贴个图,神构造,矩阵完美解决
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 55
- #define inf 1<<29
- //#define MOD 9973
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- LL m[N][N];
- }init,unit;
- LL MOD;
- Matrix Mult(Matrix m1,Matrix m2,int n){
- Matrix ans;
- memset(ans.m,0,sizeof(ans.m));
- for(int k=0;k<n;k++)
- for(int i=0;i<n;i++)
- if(m1.m[i][k])
- for(int j=0;j<n;j++){
- ans.m[i][j]+=m1.m[i][k]*m2.m[k][j];
- if(ans.m[i][j]>=MOD)ans.m[i][j]%=MOD;
- }
- /*for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=(ans.m[i][j]+m1.m[i][k]*m2.m[k][j])%MOD;
- }*/
- return ans;
- }
- Matrix Pow(Matrix m1,int b,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1,n);
- m1=Mult(m1,m1,n);
- b>>=1;
- }
- return ans;
- }
- Matrix Add(Matrix m1,Matrix m2,int n){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(m1.m[i][j]+m2.m[i][j])%MOD;
- return ans;
- }
- int n,x;
- LL c[N][N];
- int main(){
- while(scanf("%d%d%d",&n,&x,&MOD)!=EOF){
- if(n==-1&&x==-1&&MOD==-1) break;
- memset(init.m,0,sizeof(init.m));
- for(int i=0;i<=x;i++){
- c[i][0]=1;c[i][i]=1;
- for(int j=1;j<i;j++){
- c[i][j]=(c[i-1][j]+c[i-1][j-1]);
- if(c[i][j]>=MOD)
- c[i][j]-=MOD;
- }
- }
- for(int j=0;j<=x;j++)
- for(int i=0;i<=j;i++)
- init.m[i][j]=(c[j][i]*x)%MOD;
- for(int i=0;i<=x;i++)
- init.m[i][x+1]=(x*c[x][i])%MOD;
- init.m[x+1][x+1]=1;
- init=Pow(init,n-1,x+2);
- LL ans=0;
- for(int i=0;i<=x+1;i++)
- ans=(ans+(LL)x*init.m[i][x+1])%MOD;
- printf("%I64d\n",ans);
- }
- return 0;
- }
HDU 2276 Kiki & Little Kiki 2
每一个位置的状态ai=(ai+ai-1)%2,可以用异或加速
构造矩阵,便可解决
1 1 0 0 0 0 0
0 1 1 0 0 0 0
0 0 1 1 0 0 0
0 0 0 1 1 0 0
0 0 0 0 1 1 0
0 0 0 0 0 1 1
1 0 0 0 0 0 1
http://acm.hdu.edu.cn/showproblem.php?pid=2276
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 105
- #define inf 1<<29
- #define MOD 9973
- #define Max 301
- #define LL long long
- #define eps 1e-7
- #define zero(a) fabs(a)<eps
- #define equal(a,b) zero(a-b)
- using namespace std;
- struct Matrix{
- int m[N][N];
- }init,unit;
- int n,k;
- Matrix Mult(Matrix m1,Matrix m2){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++){
- ans.m[i][j]=0;
- for(int k=0;k<n;k++)
- ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%2;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1);
- m1=Mult(m1,m1);
- b>>=1;
- }
- return ans;
- }
- void debug(Matrix m1){
- for(int i=0;i<n;i++){
- for(int j=0;j<n;j++)
- printf("%d ",m1.m[i][j]);
- printf("\n");
- }
- }
- char str[N];
- int main(){
- while(scanf("%d",&k)!=EOF){
- scanf("%s",str);
- n=strlen(str);
- memset(init.m,0,sizeof(init.m));
- for(int i=0;i<n;i++)
- init.m[i][i]=init.m[(i-1+n)%n][i]=1;
- init=Pow(init,k);
- //debug(init);
- for(int i=0;i<n;i++){
- int t=0;
- for(int j=0;j<n;j++)
- t=t^((str[j]-'0')*init.m[j][i]);
- printf("%d",t);
- }
- puts("");
- }
- return 0;
- }
HDU 2855 Fibonacci Check-up
http://acm.hdu.edu.cn/showproblem.php?pid=2855
这个完全就是神构造,完全想不到,或者可以通过打表,打规律得到
- #include<iostream>
- #include<cstring>
- #include<queue>
- #include<cstdio>
- #include<cmath>
- #include<algorithm>
- #define N 2
- using namespace std;
- struct Matrix{
- int m[N][N];
- }init,unit;
- int n=2;
- int MOD;
- Matrix Mult(Matrix m1,Matrix m2){
- Matrix ans;
- memset(ans.m,0,sizeof(ans.m));
- for(int i=0;i<n;i++)
- for(int k=0;k<n;k++){
- if(m1.m[i][k])
- for(int j=0;j<n;j++)
- ans.m[i][j]=(ans.m[i][j]+(m1.m[i][k]*m2.m[k][j]))%MOD;
- }
- return ans;
- }
- Matrix Pow(Matrix m1,int b){
- Matrix ans;
- for(int i=0;i<n;i++)
- for(int j=0;j<n;j++)
- ans.m[i][j]=(i==j);
- while(b){
- if(b&1)
- ans=Mult(ans,m1);
- m1=Mult(m1,m1);
- b>>=1;
- }
- return ans;
- }
- int main(){
- int t,k;
- scanf("%d",&t);
- while(t--){
- scanf("%d%d",&k,&MOD);
- if(k==0){
- printf("0\n");
- continue;
- }
- init.m[0][0]=init.m[0][1]=init.m[1][0]=1;
- init.m[1][1]=0;
- init=Pow(init,2*k-1);
- printf("%d\n",init.m[0][0]);
- }
- return 0;
- }