 /**//*
题意:给出n个 2*2的矩阵 有m个询问,问[i,j]的矩阵的积
由于矩阵满足结合律 ABCD = (AB)(CD),即可以分离和合并
可以用线段树来做
*/
#include<cstdio>
#include<cstring>

const int MAXN = 32768;//最接近30000的2^n

 /**//*
a b
c d
*/
 struct Ma { int a,b,c,d; }x[(MAXN<<1)+1];

int R,N,M;

 inline int LC(int i) {return i<<1;}
 inline int RC(int i) {return LC(i)^1;}

void product(Ma &ret,Ma A,Ma B)
  {
ret.a = (A.a*B.a+A.b*B.c)%R;
ret.b = (A.a*B.b+A.b*B.d)%R;
ret.c = (A.c*B.a+A.d*B.c)%R;
ret.d = (A.c*B.b+A.d*B.d)%R;
}
Ma query(int p,int left,int right,int l,int r)
  {
if(left==l&&right==r)return x[p];
int mid = (left+right)>>1;
if(r<=mid)return query(LC(p),left,mid,l,r);
else if(l>mid)return query(RC(p),mid+1,right,l,r);
Ma ret;
product(ret,query(LC(p),left,mid,l,mid),query(RC(p),mid+1,right,mid+1,r));
return ret;
}
int main()
  {
//freopen("in","r",stdin);
bool blank = 0;
while(~scanf("%d%d%d",&R,&N,&M))
 {
int S = 1;
while(S<N)S<<=1;//n<=S = 2^k
for(int i=0;i<N;i++)
 {
scanf("%d%d%d%d",&x[S+i].a,&x[S+i].b,&x[S+i].c,&x[S+i].d);//read in S+i
}
//build 画一下完全二叉树就知道了
for(int i=S-1;i;i--)
 {
product(x[i],x[LC(i)],x[RC(i)]);
}
while(M--)
 {
if(blank)puts("");
else blank = 1;
int a,b;
scanf("%d%d",&a,&b);
Ma ret = query(1,1,S,a,b);
printf("%d %d\n%d %d\n",ret.a,ret.b,ret.c,ret.d);
}
}
return 0;
}
|