题目大意:
思路:
先把每一个数的排列的随机都求出来,然后按要求排序,并给每一个数搞一个左右区间判断一下。
程序:
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<iostream>
using namespace std;
typedef long long ll;
ll x0,lh;
int ans[10011];
int b[25000011],a[25000011];
int lef[5011],rig[5011];
int ax,bx,c,d,m,n,t,i,j,tot,z,u,v,lx,ly;
bool cmp(int a,int b)
{
return a<b;
}
int main()
{
scanf("%lld%d%d%d%d",&x0,&ax,&bx,&c,&d);
scanf("%d%d%d",&n,&m,&t);
for(i=1;i<=n*m;i++)a[i]=i;
for(i=1;i<=n*m;i++){
lh=(ax*x0*x0+bx*x0+c)%d;
x0=lh;
z=lh;
swap(a[z%i+1],a[i]);
}
for(i=1;i<=t;i++){
scanf("%d%d",&u,&v);
swap(a[u],a[v]);
}
for(i=1;i<=n*m;i++)b[a[i]]=i;
for(i=1;i<=n;i++){
lef[i]=1;
rig[i]=m;
}
for(i=1;i<=n*m;i++){
if(b[i]%m==0){
lx=b[i]/m;
ly=m;
}
else{
lx=b[i]/m+1;
ly=b[i]%m;
}
if(ly>=lef[lx]&&ly<=rig[lx]){
ans[++tot]=i;
for(j=1;j<=n;j++){
if(j<lx)rig[j]=min(rig[j],ly);
if(j>lx)lef[j]=max(lef[j],ly);
}
}
if(tot==n+m-1)break;
}
for(i=1;i<tot;i++)printf("%d ",ans[i]);
printf("%d\n",ans[tot]);
}