Description
Input
第 1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子。第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M 的排列来填入她 N 行 M 列的棋盘,并且小H在初始的 N×M 次交换操作后,又进行了 Q 次额外的交换操作。接下来 Q 行,第 i 行包含两个整数 u_i,v_i,表示第 i 次额外交换操作将交换 T_(u_i )和 T_(v_i ) 的值。
Output
输出一行,包含 N+M-1 个由空格隔开的正整数,表示可以得到的字典序最小的路径序列。
Sample Input
1 3 5 1 71
3 4 3
1 7
9 9
4 9
3 4 3
1 7
9 9
4 9
Sample Output
1 2 6 8 9 12
HINT
本题的空间限制是 256 MB,请务必保证提交的代码运行时所使用的总内存空间不超过此限制。
一个32位整数(例如C/C++中的int和Pascal中的Longint)为4字节,因而如果在程序中声明一个长度为 1024×1024 的32位整型变量的数组,将会占用 4 MB 的内存空间。
2≤N,M≤5000
0≤Q≤50000
0≤a≤300
0≤b,c≤108
0≤x0<d≤1081≤ui,vi≤N×M
这题先生成数据,应用贪心的思想,优先取字典序最小的,然后删除排除的情况,总之换个角度看就水过了。
1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 using namespace std; 5 int n,m,Q; 6 long long x,a,b,c,d; 7 long long Getnxt(){ 8 return (1ll*a*x*x+1ll*b*x+1ll*c)%d; 9 } 10 const int maxn=5010; 11 12 int map[maxn][maxn]; 13 int pos[maxn*maxn]; 14 int U[maxn],D[maxn],L[maxn],R[maxn]; 15 16 int main(){ 17 scanf("%lld%lld%lld%lld%lld",&x,&a,&b,&c,&d); 18 scanf("%d%d%d",&n,&m,&Q); 19 for(int i=1;i<=n;i++) 20 for(int j=1,p;j<=m;j++){ 21 x=Getnxt(); 22 p=x%(1ll*(i-1)*m+j)+1; 23 map[i][j]=(i-1)*m+j; 24 swap(map[i][j],map[(p-1)/m+1][(p-1)%m+1]); 25 } 26 for(;Q--;){ 27 int u,v; 28 scanf("%d%d",&u,&v); 29 swap(map[(u-1)/m+1][(u-1)%m+1],map[(v-1)/m+1][(v-1)%m+1]); 30 } 31 for(int i=1;i<=n;i++) 32 for(int j=1;j<=m;j++) 33 pos[map[i][j]]=(i-1)*m+j; 34 35 int cnt=0,x,y; 36 37 for(int i=1;i<=n;i++) 38 R[i]=m+1; 39 for(int i=1;i<=m;i++) 40 D[i]=n+1; 41 for(int i=1;i<=n*m;i++){ 42 x=(pos[i]-1)/m+1;y=(pos[i]-1)%m+1; 43 if(y>L[x]&&y<R[x]&&x>U[y]&&x<D[y]){ 44 ++cnt; 45 for(int j=x+1;j<=n;j++) 46 L[j]=max(L[j],y-1); 47 for(int j=x-1;j>=1;j--) 48 R[j]=min(R[j],y+1); 49 for(int j=y+1;j<=m;j++) 50 U[j]=max(U[j],x-1); 51 for(int j=y-1;j>=1;j--) 52 D[j]=min(D[j],x+1); 53 54 if(cnt!=n+m-1) 55 printf("%d ",i); 56 else 57 printf("%d",i); 58 } 59 if(cnt==n+m-1) 60 break; 61 } 62 return 0; 63 }