您的位置:首页 > 其它

[NOI2014]随机数生成器(模拟+贪心)

2015-07-14 11:42 489 查看
【题解】

先一步步按题目的操得出序列

然后在方阵中找出最小的数(对于初始方阵是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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: