http://www.lydsy.com/JudgeOnline/problem.php?id=1998

题意:

给你6个整数$n,s,q,p,m,d$。

有$n$个位置和$n-1$个盒子,位置编号从$0$开始(盒子编号从$1$开始)。一开始第$i$个盒子在第$i$个位置上,$0$号位置是空位。然后有一个$pos$序列,其中$i$位置上放的盒子是$pos_i$(其中$s$位置上必须是空位)。问:每次只能将一个盒子移动到空位上(然后这个盒子的位置变成空位),求从初始局面移动到$pos$局面的最少步数。

$pos$序列的按以下规则生成:首先生成一个序列$c$,满足$c_0=0, c_i = (c_{i-1}*q+p) \ mod \ m$,然后$pos_i = (c_i + d*x_i + y_i) \ mod \ n$,其中$x_i、y_i$是需要你来求出。但是必须满足$x_i、y_i$是非负整数,而且得到的$pos_i$不能与之前的求出的$pos$相同。如果有多个$x_i、y_i$满足条件,则优先选择$y_i$最小的;如果$y_i$相等时,则优先选择$x_i$最小的。

数据范围:上述整数均<=100000

#include <bits/stdc++.h>
using namespace std;
const int N=1000005;
typedef long long ll;
bool vis[N];
int c[N], ps[N], cnt[N], g[N], n, s, q, p, m, d;
struct dat {
int next, ok;
};
int find(int x, dat *a) {
if(a[x].ok)
return x;
int nxt=a[x].next, ret=find(nxt, a);
if(nxt!=ret)
a[x].next=a[nxt].next;
return ret;
}
dat a[N], b[N];
void init() {
d%=n;
int gr=0;
if(d==0) d=1;
for(int i=0; i<n; ++i)
a[i].next=(i+d)%n, a[i].ok=1;
for(int i=0; i<d; ++i) if(g[i]==-1) {
++gr;
for(int j=i; g[j]==-1; j=(j+d)%n)
g[j]=i, cnt[i]++;
}
a[s].ok=0;
cnt[g[s]]--;
for(int i=0; i<gr; ++i)
b[i].next=(i+1)%gr, b[i].ok=cnt[i]>0;
for(int i=1; i<n; ++i)
c[i]=((ll)c[i-1]*q+p)%m;
for(int i=1; i<n; ++i) {
c[i]%=n;
int y=(find(g[c[i]], b)+gr-g[c[i]])%gr,
pos=find((c[i]+y)%n, a);
ps[pos]=i;
a[pos].ok=0;
if(!--cnt[g[pos]]) b[g[pos]].ok=0;
}
ps[s]=0;
memset(cnt, 0, sizeof(int)*d);
memset(g, -1, sizeof(int)*n);
}
int main() {
int T; scanf("%d", &T);
memset(g, -1, sizeof g);
while(T--) {
scanf("%d%d%d%d%d%d", &n, &s, &q, &p, &m, &d);
init();
int ans=0;
for(int i=0; i<n; ++i) if(!vis[i]) {
int len=0, flag=0;
for(int j=i; !vis[j]; j=ps[j])
vis[j]=1, ++len, flag=flag+(ps[j]==0);
ans+=len>1?len+(flag?-1:1):0;
}
memset(vis, 0, sizeof(int)*n);
printf("%d\n", ans);
}
return 0;
}

  

好神的题啊..(不是太神,而是我太弱...参考题解:http://blog.163.com/benz_/blog/static/186842030201142352718885/

首先如果得到了$pos$序列,那么我们很容易根据置换群的理论计算出答案。

那么问题的难点在于求出这个$pos$序列。

发现当$c_i+y_i$固定后,所得到的$pos_i$解集是一个环!

如果$c_i+y_i$所在的环被用完了,那么$y_i$应该加上一个数$k$,使得到达一个还有没用过的位置的环!

(于是我自行yy了一个链表= =和参考题解的差不多,可是为何我的那么慢..

首先我们把环分组(每一组都是从左往右找到第一个不是其他环的数,然后一直$+d$,得到的数形成的环为一组(组编号从0开始))。发现这样做得到最多不超过$d$个组。

令最后一个非空组为$j$,第一个组为$i=0$,而由于$j$后面的空组是没用的(即$j$上的数如果$+1$就到达了$i$上的数,并没有经过后面的空组),所以我们只需要看成有$j+1$个组即可。

而又发现,组与组的距离(就是从一个组上的数加这个距离得到了另一个组上的数)其实是模$j+1$的减法!(比如$a$组和$b$组的距离$k$就是满足$a+k \equiv b \pmod{j+1}$的最小的$k$,那么$a$组上的数加上$k$一定是$b$组上的数)。

而在每一组内,我们同样将环内元素用一个链表来搞,只不过在查找的时候用了类似并查集的路径压缩做法(复杂度应该是均摊$O(n)$的??QAQ),就是说如果一个点被删除了,而这个点的后继是非空环,那么前驱的后继连到这个点的后继,递归处理一下即可。

(还有发现$d=0$的情况其实可以看做$d=1$的情况,因此特判一下把$d$变成1就行辣~

【BZOJ】1998: [Hnoi2010]Fsk物品调度的更多相关文章

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

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

  2. 【BZOJ 1998】 1998: [Hnoi2010]Fsk物品调度(双向链表+并查集+置换)

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

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

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

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

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

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

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

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

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

  7. [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree)

    [BZOJ 2002] [HNOI2010]弹飞绵羊(Link Cut Tree) 题面 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一 ...

  8. [HNOI2010] 物品调度 fsk

    标签:链表+数论知识. 题解: 对于这道题,其实就是两个问题的拼凑,我们分开来看. 首先要求xi与yi.这个可以发现,x每增加1,则pos增加d:y每增加1,则pos增加1.然后,我们把x与y分别写在 ...

  9. [HNOI2010]物品调度

    题目描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostm ...

随机推荐

  1. poj 2262【素数表的应用---判断素数】【哈希】

    Goldbach's Conjecture Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 35214   Accepted: ...

  2. 学习SQLAlchemy Core

    有时间了就要慢慢看,死守DJANGO ORM,明显没有SQLAlchemy有优势. 因为SQLAlchemy针对整个PYTHON都是有用的. 找了本书,慢慢撸. <Essential.SQLAl ...

  3. OCJP(1Z0-851) 模拟题分析(八)over

    Exam : 1Z0-851 Java Standard Edition 6 Programmer Certified Professional Exam 以下分析全都是我自己分析或者参考网上的,定有 ...

  4. [LeetCode] Same Tree

    Given two binary trees, write a function to check if they are equal or not. Two binary trees are con ...

  5. linux 读写锁应用实例

    转自:http://blog.csdn.net/dsg333/article/details/22113489 /*使用读写锁实现四个线程读写一段程序的实例,共创建了四个新的线程,其中两个线程用来读取 ...

  6. VMWARE虚拟机CentOS6.4系统使用主机无线网卡上网的三种方法介绍

    转自:http://www.jb51.net/network/98820.html 如何真正的实现VMWARE虚拟机CentOS6.4系统使用主机无线网卡上网   环境:WIN7旗舰版,台式机,U盘无 ...

  7. C++ 简单的学生信息管理系统

    // // main.cpp // 2013-7-17作业1 // // Created by 丁小未 on 13-7-17. // Copyright (c) 2013年 dingxiaowei. ...

  8. 【荐】Spring事务配置的五种方式

    Spring配置文件中关于事务配置总是由三个组成部分,分别是DataSource.TransactionManager和代理机制这三部分,无论哪种配置方式,一般变化的只是代理机制这部分. DataSo ...

  9. h5嵌入视频遇到的bug及总结---转载

    最近做的一个h5活动因为嵌入视频而发现了好多以前从未发现的问题,在测试的时候不同系统不同版本不同环境等多多少少都出现了些问题,搞得我也是焦头烂额的,不过好在最终问题都解决了,自己也学到了好多东西,为了 ...

  10. C# 溢出检查

    checked: byte b = 255; checked { b++; } Console.WriteLine(b.ToString()); 执行出错:算术运算导致溢出. unchecked: b ...