【题解】
先一步步按题目的操得出序列
然后在方阵中找出最小的数(对于初始方阵是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;
}