[BZOJ3671][UOJ#6][NOI2014]随机数生成器

试题描述

小H最近在研究随机算法。随机算法往往需要通过调用随机数生成函数(例如Pascal中的random和C/C++中的rand)来获得随机性。事实上,随机数生成函数也并不是真正的“随机”,其一般都是利用某个算法计算得来的。

比如,下面这个二次多项式递推算法就是一个常用算法:

算法选定非负整数x0,a,b,c,d作为随机种子,并采用如下递推公式进行计算。

对于任意i≥1,xi=(ax2i−1+bxi−1+c)mod d 。

这样可以得到一个任意长度的非负整数数列{xi}i≥1,一般来说,我们认为这个数列是随机的。

利用随机序列{xi}i≥1,我们还可以采用如下算法来产生一个1到K的随机排列{Ti}i=1~K :

  1. 初始设T为1到K的递增序列;
  2. 对T进行K次交换,第i次交换,交换Ti和T(ximodi)+1的值。

此外,小H在这K次交换的基础上,又额外进行了Q次交换操作,对于第i次额外交换,小H会选定两个下标ui和vi,并交换Tui和Tvi的值。

为了检验这个随机排列生成算法的实用性,小H设计了如下问题:

小H有一个N行M列的棋盘,她首先按照上述过程,通过N×M+Q次交换操作,生成了一个 1∼N×M的随机排列{Ti}N×Mi=1然后将这N×M个数逐行逐列依次填入这个棋盘:也就是第 i行第 j列的格子上所填入的数应为T(i−1)×M+j。

接着小H希望从棋盘的左上角,也就是第一行第一列的格子出发,每次向右走或者向下走,在不走出棋盘的前提下,走到棋盘的右下角,也就是第N行第M列的格子。

小H把所经过格子上的数字都记录了下来,并从小到大排序,这样,对于任何一条合法的移动路径,小H都可以得到一个长度为N+M−1的升序序列,我们称之为路径序列

小H想知道,她可能得到的字典序最小路径序列应该是怎样的呢?

输入

输入文件的第1行包含5个整数,依次为x0,a,b,c,d,描述小H采用的随机数生成算法所需的随机种子。

第2行包含三个整数 N,M,Q,表示小H希望生成一个11 到N×M的排列来填入她N行M列的棋盘,并且小H在初始的N×M次交换操作后,又进行了Q次额外的交换操作。

接下来Q行,第i行包含两个整数ui,vi,表示第i次额外交换操作将交换 Tui和Tvi的值

输出

输出一行,包含 N+M−1个由空格隔开的正整数,表示可以得到的字典序最小的路径序列。

输入示例1


输出示例1

     

输入示例2

  

输出示例2

                  

输入示例3

  

输出示例3

                                      

输入示例4

传送门(点击下载)

输出示例4

传送门

数据规模及约定

2≤N,M≤5000

0≤Q≤50000

0≤a≤300

0≤b,c≤108

0≤x0<d≤108

1≤ui,vi≤N×M

题解

既然要求排完序之后的字典序最小,那显然可以用贪心来解决。

先把起点和终点的数加进来,之后从1到n·m依次判断。判断数i时先找到i左边最靠近i的一列(称为列L),再找到右边最靠近i的一列(称为列R),以列L中已插入的最靠下的位置和列R中已插入的最靠上的位置分别作为矩形的左上、右下顶点,若i在这个矩形内部则可以取到,否则不能取到。对于每一个可以去到的i,将其行、列的位置加进来。

这个好像可以用线段树搞?

仔细看题,加入操作不超过9999次(n + m - 1次),所以暴!力!即!可!【用线段树反而会多一个log】

下面这个代码是97分的,感谢UOJ用户 r_64 的hack,帮我找到了代码的Bug。(读者不妨看看我错在哪里)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
if(Head == tail) {
int l = fread(buffer, 1, BufferSize, stdin);
tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 5010
#define maxm 25000010
#define LL long long
int n, m, q, x[maxm], T[maxm], tl[maxn], tr[maxn], high[maxn], low[maxn]; int ans[maxn<<1], cnt;
short idy[maxm];
int main() {
x[0] = read(); int a = read(), b = read(), c = read(), d = read();
n = read(); m = read(); q = read();
for(int i = 1; i <= n * m; i++) {
x[i] = (((LL)a * x[i-1] * x[i-1]) % d + ((LL)b * x[i-1]) % d + c) % d;
T[i] = i;
}
for(int i = 1; i <= n * m; i++) swap(T[i], T[x[i]%i+1]);
while(q--) {
int x = read(), y = read();
if(x != y) swap(T[x], T[y]);
}
for(int i = 1; i <= n * m; i++)
x[T[i]] = (i-1) / m + 1, idy[T[i]] = (i-1) % m + 1; for(int i = 2; i < m; i++) tl[i] = 1, tr[i] = m, high[i] = n+1, low[i] = 0;
high[1] = low[1] = 1; high[m] = low[m] = n;
for(int i = 1; i <= n * m; i++) if(i != T[1] && i != T[n*m]) {
int X = x[i], y = idy[i];
if((y == 1 || low[tl[y]] <= X) && (y == m || X <= high[tr[y]])) {
ans[++cnt] = i;
for(int j = tl[y]; j < y; j++) tr[j] = y;
for(int j = y+1; j <= tr[y]; j++) tl[j] = y;
// printf("%d %d %d\n", i, x, y);
// for(int j = 1; j <= m; j++) printf("%d ", tl[j]); putchar('\n');
// for(int j = 1; j <= m; j++) printf("%d ", tr[j]); putchar('\n');
low[y] = max(low[y], X); high[y] = min(high[y], X);
}
}
else ans[++cnt] = i; for(int i = 1; i < cnt; i++) printf("%d ", ans[i]); printf("%d\n", ans[cnt]); return 0;
}

100分:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <stack>
#include <vector>
#include <queue>
#include <cstring>
#include <string>
#include <map>
#include <set>
using namespace std; const int BufferSize = 1 << 16;
char buffer[BufferSize], *Head, *tail;
inline char Getchar() {
if(Head == tail) {
int l = fread(buffer, 1, BufferSize, stdin);
tail = (Head = buffer) + l;
}
return *Head++;
}
int read() {
int x = 0, f = 1; char c = Getchar();
while(!isdigit(c)){ if(c == '-') f = -1; c = Getchar(); }
while(isdigit(c)){ x = x * 10 + c - '0'; c = Getchar(); }
return x * f;
} #define maxn 5010
#define maxm 25000010
#define LL long long
int n, m, q, x[maxm], T[maxm], tl[maxn], tr[maxn], high[maxn], low[maxn]; int ans[maxn<<1], cnt;
short idy[maxm];
int main() {
x[0] = read(); int a = read(), b = read(), c = read(), d = read();
n = read(); m = read(); q = read();
for(int i = 1; i <= n * m; i++) {
x[i] = (((LL)a * x[i-1] * x[i-1]) % d + ((LL)b * x[i-1]) % d + c) % d;
T[i] = i;
}
for(int i = 1; i <= n * m; i++) swap(T[i], T[x[i]%i+1]);
while(q--) {
int x = read(), y = read();
if(x != y) swap(T[x], T[y]);
}
for(int i = 1; i <= n * m; i++)
x[T[i]] = (i-1) / m + 1, idy[T[i]] = (i-1) % m + 1; for(int i = 1; i <= m; i++) tl[i] = 1, tr[i] = m, high[i] = n+1, low[i] = 0;
high[1] = low[1] = 1; high[m] = low[m] = n;
for(int i = 1; i <= n * m; i++) if(i != T[1] && i != T[n*m]) {
int X = x[i], y = idy[i];
if((y == 1 || low[tl[y]] <= X) && (y == m || X <= high[tr[y]])) {
ans[++cnt] = i;
for(int j = tl[y]; j < y; j++) tr[j] = y;
for(int j = y+1; j <= tr[y]; j++) tl[j] = y;
// printf("%d %d %d\n", i, x, y);
// for(int j = 1; j <= m; j++) printf("%d ", tl[j]); putchar('\n');
// for(int j = 1; j <= m; j++) printf("%d ", tr[j]); putchar('\n');
low[y] = max(low[y], X); high[y] = min(high[y], X);
}
}
else ans[++cnt] = i; for(int i = 1; i < cnt; i++) printf("%d ", ans[i]); printf("%d\n", ans[cnt]); return 0;
}

[BZOJ3671][UOJ#6][NOI2014]随机数生成器的更多相关文章

  1. 【BZOJ3671】[Noi2014]随机数生成器 暴力

    [BZOJ3535][Noi2014]随机数生成器 Description Input 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第2行包含三个 ...

  2. BZOJ_3671_[Noi2014]随机数生成器_set+贪心

    BZOJ_3671_[Noi2014]随机数生成器_set Description   Input 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第 ...

  3. NOI2014 随机数生成器

    随机数生成器 [问题描述] 小H最近在研究随机算法.随机算法往往需要通过调用随机数生成函数(例如Pascal中的random和C/C++中的rand)来获得随机性.事实上,随机数生成函数也并不是真正的 ...

  4. luogu P2354 [NOI2014]随机数生成器 贪心 卡空间 暴力

    LINK:随机数生成器 观察数据范围还是可以把矩阵给生成出来的. 考虑如何求出答案.题目要求把选出的数字从小到大排序后字典序尽可能的小 实际上这个类似于Mex的问题. 所以要从大到小选数字 考虑选择一 ...

  5. BZOJ3671 [Noi2014]随机数生成器 【贪心】

    题目链接 BZOJ3671 题解 模拟题意生成矩阵贪心从小选择即可 每选择一个,就标记其左下右上矩阵 由于每次都是标记一个到边界的矩阵,所以一旦遇到标记过就直接退出即可,可以保证复杂度 还有就是空间和 ...

  6. BZOJ3671/UOJ6 [Noi2014]随机数生成器

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000 作者博客:http://www.cnblogs.com/ljh2000-jump/ ...

  7. bzoj3671 [Noi2014]随机数生成器

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3671 [题解] 贪心从1...n*m取,开两个5000*5000的数组就够了,可以重复利用, ...

  8. BZOJ3671: [Noi2014]随机数生成器(贪心)

    Time Limit: 50 Sec  Memory Limit: 256 MBSubmit: 2098  Solved: 946[Submit][Status][Discuss] Descripti ...

  9. 【bzoj3671】[Noi2014]随机数生成器 贪心

    题目描述 输入 第1行包含5个整数,依次为 x_0,a,b,c,d ,描述小H采用的随机数生成算法所需的随机种子.第2行包含三个整数 N,M,Q ,表示小H希望生成一个1到 N×M 的排列来填入她 N ...

随机推荐

  1. [USACO2005][POJ3169]Layout(差分约束)

    题目:http://poj.org/problem?id=3169 题意:给你一组不等式了,求满足的最小解 分析: 裸裸的差分约束. 总结一下差分约束: 1.“求最大值”:写成"<=& ...

  2. 08.C# System.Nulable<T>和空引用操作符(四章4.2-4.4)

    看了这3小节,发现作者讲得太详细了,把一个都在正常使用的用法说得太神密了,搞得不知是自己不懂作者的苦心,还是作者用意为之,这里给大家都简单讲下吧,太深的真心讲不下去. 1.可空类型的核心部分是Syst ...

  3. 编写高质量代码改善C#程序的157个建议[用抛异常替代返回错误、不要在不恰当的场合下引发异常、重新引发异常时使用inner Exception]

    前言 自从.NET出现后,关于CLR异常机制的讨论就几乎从未停止过.迄今为止,CLR异常机制让人关注最多的一点就是“效率”问题.其实,这里存在认识上的误区,因为正常控制流程下的代码运行并不会出现问题, ...

  4. 北京大学信息科学技术学院计算机专业课程大纲选摘--JAVA

  5. 转: maven进阶:一个多模块项目

    一个多模块项目通过一个父POM 引用一个或多个子模块来定义.父项目,通过以下配置,将子项目关联. <packaging>pom</packaging> <modules& ...

  6. Java-如何挖取某个网站中的ajax请求信息

    通常情况,通过网络爬虫挖取到的基本为网页静态内容,而动态ajax取数的内容是我个人暂时不知如何一次性把网站中的ajax获取 这里介绍的是某个网站中的某一个ajax多某个table刷新,期数据,并提供其 ...

  7. 【CodeForces 504A】Misha and Forest

    题 题意 有n个点,代号分别为0到n-1,然后这n个点有d个相连点,相连点的XOR sum 为s,求所有的边. 分析 知识:a^b^a=b,a^b^b=a. 把相连点为1的i存进队列,i的唯一相连点就 ...

  8. spring - ioc和aop

    1.程序中为什么会用到spring的ioc和aop 2.什么是IOC,AOP,以及使用它们的好处,即详细回答了第一个问题 3.原理 关于1: a:我们平常使用对象的时候,一般都是直接使用关键字类new ...

  9. 宿主机( win 7 系统) ping 虚拟机VMware( cent os 6.6 ) 出现“请求超时”或者“无法访问目标主机”的解决方法

    首先虚拟机的网络连接设置为"Host-only": 然后在 cmd 窗口中查看 VMnet1 的 ip 地址,这里是 192.168.254.1 接下来在 Linux 中设置网卡地 ...

  10. ETHREAD APC 《寒江独钓》内核学习笔记(4)

    继续学习windows 中和线程有关系的数据结构: ETHREAD.KTHREAD.TEB 1. 相关阅读材料 <windows 内核原理与实现> --- 潘爱民 2. 数据结构分析 我们 ...