[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. .NET 关键字

    一.base关键字 可以通过base关键字访问上一级父类方法的访问.静态static函数无法调用base 二.new 关键字new new有2个作用. new运算符   用来分配内存空间和初始化对象. ...

  2. RequireJS实例分析

    随着JS越来越庞大,已经不仅仅是以前复制粘贴做特效的时代了,JS越来越偏向于业务逻辑与应用.恰逢Node的流行,JS在web开发中占有越来越重要的地位.由于JS代码庞大,文件数目多,传统的使用< ...

  3. 解决HTML5布局,兼容IE问题

    当我们使用h5的新标签,header,footer,aside,section,article...时,会遇到低版本IE不兼容问题,如下图: 解决方案:引入如下JS代码,即可 (这里我就直接放源码了, ...

  4. cursor:pointer的意思

    cursor规则是设定网页浏览时用户鼠标指针的样式,也就是鼠标的图形形状cursor:pointer设定鼠标的形状为一只伸出食指的手,这也是绝大多数浏览器里面鼠标停留在网页链接上方时候的样式另外可以选 ...

  5. Hibernate-二级缓存 sessionFactory

    Hibernate 二级缓存 二级缓存需要sessionFactory来管理,它是进初级的缓存,所有人都可以使用,它是共享的. 当Hibernate根据ID访问数据对象的时候,首先从Session一级 ...

  6. SQL Server之存储过程基础知识

    什么是存储过程呢?存储过程就是作为可执行对象存放在数据库中的一个或多个SQL命令. 通俗来讲:存储过程其实就是能完成一定操作的一组SQL语句. 那为什么要用存储过程呢?1.存储过程只在创造时进行编译, ...

  7. 【POJ 3020】Antenna Placement(二分图匹配)

    相当于用1*2的板覆盖给定的h*w的格子里的点,求最少的板.可以把格子相邻的分成两个集合,如下图,0为一个集合,1的为一个,也就是(行数+列数)为奇数的是一个集合,为偶数的为另一个集合.1010101 ...

  8. BZOJ-1206 虚拟内存 Hash+离散化+Priority_Queue

    闻说HNOI每年都有一道Hash. 1206: [HNOI2005]虚拟内存 Time Limit: 50 Sec Memory Limit: 162 MB Submit: 330 Solved: 2 ...

  9. 洛谷P1121 环状最大两段子段和

    题目描述 给出一段环状序列,即认为A[1]和A[N]是相邻的,选出其中连续不重叠且非空的两段使得这两段和最大. 输入输出格式 输入格式: 输入文件maxsum2.in的第一行是一个正整数N,表示了序列 ...

  10. Code Review Engine Learning

    相关学习资料 https://www.owasp.org/index.php/Code_review https://www.owasp.org/images/8/8e/OWASP_Code_Revi ...