【题解】
先一步步按题目的操得出序列
然后在方阵中找出最小的数(对于初始方阵是1)的位置(x,y)
再在矩阵(1,1)-(x,y),(x,y)-(n,m)中分别找出最小数的位置
递归是没必要的,也不容易找出每个子矩阵内最小的数
可以反过来考虑:
1,2,3……能不能依次使用?
1肯定可以,2的话,必须在1划分出的子矩阵(1,1)-(x,y)或(x,y)-(n,m)中才行
若2能放入,则2也参与了对可行区域的划分(或者说限制)
之后再判断3……
画图可知,每一行的可行区间是连续的
这样只需知道每一行的可行区间left[i],right[i],往答案中加入数时维护之即可
【代码】
用快速乘就TLE了,时限不是5s吗,怎么回事。。。
此题结尾不能输出多余空格
#include<stdio.h> #include<stdlib.h> int num[25000005],bel[25000005],left[5005],right[5005]; void jh(int* a,int* b) { int t=*a; *a=*b; *b=t; } int main() { long long a,b,c,d,X; int n,m,Q,i,j,k,x,y,cnt; scanf("%lld%lld%lld%lld%lld%d%d%d",&X,&a,&b,&c,&d,&n,&m,&Q); cnt=n*m; for(i=1;i<=cnt;i++) num[i]=i; for(i=1;i<=cnt;i++) { X=(a*X%d*X+b*X+c)%d; jh(&num[i],&num[(int)X%i+1]); } for(;Q>0;Q--) { scanf("%d%d",&i,&j); jh(&num[i],&num[j]); } for(i=1;i<=cnt;i++) bel[num[i]]=i; for(i=1;i<=n;i++) { left[i]=1; right[i]=m; } j=0; for(i=1;i<=n+m-1;i++) { do { j++; x=(bel[j]-1)/m+1; y=(bel[j]-1)%m+1; } while(y<left[x]||y>right[x]); for(k=1;k<x;k++) if(right[k]>y) right[k]=y; for(k=x+1;k<=n;k++) if(left[k]<y) left[k]=y; if(i>1) printf(" "); printf("%d",j); } return 0; }