[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. 最新app store 应用提交经验分享

    由于之前提交实在3月份的时候,后来长时间没有提交了,最近又需要提交,发现苹果已经发生翻天覆地的变化了,真是跟不上时代了啊.... 之前提交的基本也是从网上看的,前面的证书安装部分其实基本是一样的没什么 ...

  2. jQuery理解之(一)动画与特效

    本节主要降级和学习jQuery的自动显隐,渐入渐出.飞入飞出.自定义动画等. 1.显示和隐藏hide()和show() 对于动画来说,显示和隐藏是最基本的效果之一,本节简单介绍jQuery的显示和隐藏 ...

  3. 第六章:javascript:字典

    字典是一种以键-值对应形式存储的数据结构,就像电话薄里的名字和电话号码一样.只要找一个电话,查找名字,名字找到后,电话号码也就找到了.这里的键值是你用来查找的东西,值就是要查的到的结果. javasc ...

  4. Servlet学习 (HttpServletRequest HttpServletResponse)

    1.什么事servlet? 答:服务器端程序, 自定义的服务类型.tomcat是一个容器,这个容器提供各种菜的服务, 我们需要为里面放菜! web服务器就是我们的开发环境和开发基础. 实现了servl ...

  5. ibatis中的$和#的区别

    介绍 在Ibatis中我们使用SqlMap进行Sql查询时需要引用参数,在参数引用中遇到的符号#和$之间的区分为,#可以进行与编译,进行类型匹配,而$不进行数据类型匹配,例如: select * fr ...

  6. WordPress HOOK机制原理及代码分析

    WordPress强大的插件机制让我们可以自由扩展功能.网上对插件的使用以及开发方法都有大量资料可以查询. 今天我们就分析一下四个主要函数的代码,包括: add_action.do_action.ad ...

  7. __name__和__main的含义

    if __name__ == "__main__": main() This module represents the (otherwise anonymous) scope i ...

  8. hdu 1166 敌兵布阵--BIT

    BIT模版题,学完直接刷毫无压力,水的不要不要的 敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Ja ...

  9. Using a Comparison Function for the Key Type

    (这是C++系列随笔的第二篇,这一系列是我练习C++而查的资料) C++ Primer 5th. Ed. pp. 425 ---------------------- Using a Comparis ...

  10. jboss7.1.1配置mysql数据源

    http://blog.csdn.net/msz1992/article/details/8826754 #1.到http://www.mysql.com/downloads/connector/j/ ...