1998: [Hnoi2010]Fsk物品调度

Description

现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位。流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子。Lostmonkey要按照以下规则重新排列这些盒子。 规则由5个数描述,q,p,m,d,s,s表示空位的最终位置。首先生成一个序列c,c0=0,ci+1=(ci*q+p) mod m。接下来从第一个盒子开始依次生成每个盒子的最终位置posi,posi=(ci+d*xi+yi) mod n,xi,yi是为了让第i个盒子不与之前的盒子位置相同的由你设定的非负整数,且posi还不能为s。如果有多个xi,yi满足要求,你需要选择yi最小的,当yi相同时选择xi最小的。 这样你得到了所有盒子的最终位置,现在你每次可以把某个盒子移动到空位上,移动后原盒子所在的位置成为空位。请问把所有的盒子移动到目的位置所需的最少步数。

Input

第一行包含一个整数t,表示数据组数。接下来t行,每行6个数,n,s,q,p,m,d意义如上所述。 对于30%的数据n<=100,对于100%的数据t<=20,n<=100000,s<n。其余所有数字均为不超过100000的正整数。 <="" div="">

Output

对于每组数据输出一个数占一行,表示最少移动步数。

Sample Input

1
8 3 5 2 7 4

Sample Output

6

HINT

说明:第1个到第7个盒子的最终位置依次是:2 5 6 4 1 0 7
计算过程可能超过整型范围。

Source

【分析】

  啊,我好笨。

  先看那两个公式。

  ci+1=(ci*q+p) mod m

  posi=(ci+d*xi+yi) mod n

  观察题目就知道主要是求pos数组,后面的就是置换的很基本的东西,弄成循环就好了。

  pos数组怎么求呢,当然暴力是会超时的。

  观察一下他的形式,发现如果yi也固定,那么走的是一个环。

  如果这个环里面所有元素都被取走了,那么就跳到下一个环,直到环里面有东西为止。

  就是模拟一个这样的过程,然后当然虽说是跳直到找到有环,但当然还是不能这样做的,所以我用了并查集和双向链表搞这个东西。

  环的数量是gcd(n,d)【表示我一开始还搞错这个很久

  求出pos数组之后,把置换分成互不相交的循环

  若循环长度>1,且空格在里面,则ans+=L-1

  否则ans+=L+1

  【最后那部分还是很简单的】

 #include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 1000010
#define INF 0xfffffff
#define LL long long int n,s,m,d;
int nt[Maxn],lt[Maxn],fa[Maxn];//环
int ntt[Maxn],ltt[Maxn],fax[Maxn];//环集
int pos[Maxn],id[Maxn];
LL c[Maxn],q,p; int ffa(int x)
{
if(fa[x]!=x) fa[x]=ffa(fa[x]);
return fa[x];
} int ffax(int x)
{
if(fax[x]!=x) fax[x]=ffax(fax[x]);
return fax[x];
} int gcd(int a,int b)
{
if(b==) return a;
return gcd(b,a%b);
} bool vis[Maxn]; int main()
{
int T;
scanf("%d",&T);
while(T--)
{
int L;
scanf("%d%d%lld%lld%d%d",&n,&s,&q,&p,&m,&d);
d%=n;
for(int i=;i<n;i++) nt[i]=(i+d)%n;
for(int i=;i<n;i++) lt[i]=(i-d+n)%n;
c[]=;
for(int i=;i<n;i++) c[i]=(c[i-]*q+p)%m;
for(int i=;i<n;i++) fa[i]=i;
for(int i=;i<n;i++) c[i]%=n;
if(d!=) L=gcd(n,d);
else L=n;
for(int i=;i<L;i++) fax[i]=i;
for(int i=;i<L;i++)
{
id[i]=i;
int x=nt[i];
while(x!=i)
{
id[x]=i;
x=nt[x];
}
} memset(vis,,sizeof(vis));
for(int i=;i<n;i++)
{
int nw=ffax(id[c[i]]); pos[i]=ffa((c[i]+(nw-id[c[i]]+L)%L)%n); if(i==) pos[i]=s,nw=s%L;
if(lt[pos[i]]==pos[i])
{
fax[nw]=(nw+)%L;
}
else
{
nt[lt[pos[i]]]=nt[pos[i]];
lt[nt[pos[i]]]=lt[pos[i]];
fa[pos[i]]=nt[pos[i]];
}
}
LL ans=;
memset(vis,,sizeof(vis));
for(int i=;i<n;i++) if(vis[i]==)
{
int x=i,cnt=;
bool p=;
while(vis[x]==)
{
cnt++;
if(x==s) p=;
vis[x]=;
x=pos[x];
}
if(cnt>)
{
if(p) ans+=cnt-;
else ans+=cnt+;
}
}
printf("%d\n",ans);
}
return ;
}

2017-01-13 09:30:25

【BZOJ 1998】 1998: [Hnoi2010]Fsk物品调度(双向链表+并查集+置换)的更多相关文章

  1. BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换

    BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换 Description 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置 ...

  2. 【BZOJ 1998】[Hnoi2010]Fsk物品调度 置换群+并查集

    置换群的部分水得一比,据说是经典的置换群理论(然而我并不知道这理论是啥).重点就在于怎么求pos!!!容易发现这个东西是这样的:每次寻找pos,先在本环里找,找不到再往下一个环里找,直到找到为止……一 ...

  3. BZOJ 1998: [Hnoi2010]Fsk物品调度 [置换群 并查集]

    传送门 流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostmonkey要按照以下规则重新排列这些盒子. 规则由5个数描述,q,p,m,d,s,s表示空 ...

  4. [BZOJ1998][Hnoi2010]Fsk物品调度

    [BZOJ1998][Hnoi2010]Fsk物品调度 试题描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开 ...

  5. 【BZOJ1998】[HNOI2010]物品调度(并查集,模拟)

    [BZOJ1998][HNOI2010]物品调度(并查集,模拟) 题面 BZOJ,为啥这题都是权限题啊? 洛谷 题解 先不管\(0\)位置是个空,把它也看成一个箱子.那么最终的答案显然和置换循环节的个 ...

  6. 【BZOJ】1998: [Hnoi2010]Fsk物品调度

    http://www.lydsy.com/JudgeOnline/problem.php?id=1998 题意: 给你6个整数$n,s,q,p,m,d$. 有$n$个位置和$n-1$个盒子,位置编号从 ...

  7. HNOI 2010 物品调度 并查集 置换

    题意: 题意有点细,暂不概括.请仔细审题. 分析: 我们先要把c生成出来. 记得颜神讲这道题,首先表明,这道题有两个问题需要处理. 第一个是要先定位,第二个是要求最小移动步数. 定位时对于每一个物品i ...

  8. 【BZOJ】1202: [HNOI2005]狡猾的商人(并查集+前缀和)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1202 用并查集+前缀和. 前缀和从后向前维护和,并查集从前往后合并 对于询问l, r 如果l-1和r ...

  9. 【BZOJ】1016: [JSOI2008]最小生成树计数 深搜+并查集

    最小生成树计数 Description 现在给出了一个简单无向加权图.你不满足于求出这个图的最小生成树,而希望知道这个图中有多少个不同的最小生成树.(如果两颗最小生成树中至少有一条边不同,则这两个最小 ...

随机推荐

  1. 【bzoj3387-跨栏训练】线段树+dp

    我们可以想到一个dp方程:f[i][0]表示当前在i个栅栏的左端点,f[i][1]表示在右端点. 分两种情况: 第一种:假设现在要更新线段gh的左端点g,而它下来的路径被ef挡住了,那么必定是有ef来 ...

  2. js 的function为什么可以添加属性

    (1) function person(){ this.name = 'Tom'; } (2) function person(){} person.name = 'Tom'; (3) functio ...

  3. js常用模板引擎

    baiduTemplate(百度).artTemplate(腾讯).juicer(淘宝).xtemplate.doT.Jade 1.Handlebars 是 JavaScript 一个语义模板库,通过 ...

  4. [NOI2008] [bzoj1061] 志愿者招募

    还是一道费用流的题目.话不多说,进入正题. 题意:给定n个点和m种从l到r覆盖一层的费用,求满足所有点的覆盖层数都大等于权值的最小费用 分析:要做到区间修改,看似比较麻烦. 用差分把区间修改变成单点修 ...

  5. bzoj 1179 Atm

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1179 题解: 一道比较综合的图论题 直接讲正解: 如果这个图G中存在某个强连通分量,那么这 ...

  6. java数组面试题

    一维数组可以写成:int[ ]x 或者int x[ ]: 二维数组可以写成:int[ ] y [ ] 或者int y[ ][ ] 或者int [ ][ ]y 面试题如下:       声明数组int[ ...

  7. Makefile系列之四 :条件判断

    一.示例 下面的例子,判断$(CC)变量是否“gcc”,如果是的话,则使用GNU函数编译目标. libs_for_gcc = -lgnu normal_libs = foo: $(objects) i ...

  8. 【python】时间戳、字典列表排序

    记录一下昨天学到的知识: 一.文件相关 文件追加:f = open("fname","a")    文件不存在时创建 二.时间戳相关 http://www.jb ...

  9. How ConcurrentHashMap offers higher concurrency without compromising thread safety

    https://www.ibm.com/developerworks/library/j-jtp08223/

  10. C# 实现动态添加列,新增合计行,求和

    DataTable da = CommonBLL.GetList("*", "sys_dict", "IfState=1 and DictTypeId ...