1. 程式人生 > >【BZOJ3671】[Noi2014]隨機數生成器 暴力

【BZOJ3671】[Noi2014]隨機數生成器 暴力

put noi2014 noi get ems amp name light urn

【BZOJ3535】[Noi2014]隨機數生成器

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

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

題解:矩陣生成的方法。。。它讓你怎麽做你就怎麽做就行了,不過有點卡空間,以後不再用到的數組可以廢物利用一下~

然後輸出路徑。。。直接每次貪心看一下最小的那個數能不能選,如果能,就暴力將它的左下和右上方(嚴格)的所有格子標記為不能選,註意不要重復打標記。

#include <cstdio>
#include <cstring>
#include <iostream>
#define P(A,B) ((A-1)*m+B)
#define X(A) ((A-1)/m+1)
#define Y(A) ((A-1)%m+1)
using namespace std;
typedef long long ll;
int n,m,q,A,B,C,D;
ll x0;
int p[25000010],v[25000010];
int rd()
{
	int ret=0,f=1;	char gc=getchar();
	while(gc<‘0‘||gc>‘9‘)	{if(gc==‘-‘)f=-f;	gc=getchar();}
	while(gc>=‘0‘&&gc<=‘9‘)	ret=ret*10+gc-‘0‘,gc=getchar();
	return ret*f;
}
int main()
{
	x0=rd(),A=rd(),B=rd(),C=rd(),D=rd(),n=rd(),m=rd(),q=rd();
	int i,j,k,a,b,flag=0;
	for(i=1;i<=n*m;i++)	v[i]=i;
	for(i=1;i<=n*m;i++)	x0=(A*x0*x0+B*x0+C)%D,swap(v[i],v[x0%i+1]);
	for(i=1;i<=q;i++)	a=rd(),b=rd(),swap(v[a],v[b]);
	for(i=1;i<=n*m;i++)	p[v[i]]=i;
	memset(v,0,sizeof(v));
	for(i=1;i<=n*m;i++)
	{
		if(v[p[i]])	continue;
		a=X(p[i]),b=Y(p[i]);
		if(flag)	printf(" ");
		flag=1;
		printf("%d",i);
		for(j=a+1;j<=n;j++)
		{
			if(v[P(j,b-1)])	break;
			for(k=b-1;k;v[P(j,k)]=1,k--)	if(v[P(j,k)])	break;
		}
		for(j=a-1;j;j--)
		{
			if(v[P(j,b+1)])	break;
			for(k=b+1;k<=m;v[P(j,k)]=1,k++)	if(v[P(j,k)])	break;
		}
	}
	return 0;
}

【BZOJ3671】[Noi2014]隨機數生成器 暴力