[HNOI2010] 物品调度 fsk
标签:链表+数论知识。
题解:
对于这道题,其实就是两个问题的拼凑,我们分开来看。
首先要求xi与yi。这个可以发现,x每增加1,则pos增加d;y每增加1,则pos增加1。然后,我们把x与y分别写在二维平面上,比如样例:
x= 0 1
y=0 {0 4}
y=1 {1 5}
y=2 {2 6}
y=3 {3 7}
发现行数=gcd(n,d),列数=n/gcd(n,d)。
那么题目要求y尽量小,然后x尽量小。我们先求y,那么初始pos就是ci,把ci放入这张表,寻找最近的可以不重复的行,也就是y。找到之后我们再把ci+y代入,去找在第y行的哪一个数是最近的,这样就能找到x与y了。
具体的:我们使用rx[i],代表x=i时,右边那个可用的是哪一个,rx_cnt[i]代表距离。同样ry[i],与ry_cnt[i]分别表示y=i的下面的哪一个与距离。每次修改(也就是标记Val已经被使用)仅仅需要对于(Val+d)%n即可,然后rx[Val]=(Val+d)%n,rx_cnt[Val]=1。将Val%=gcd,即可完成对于y的修改。
修改那么简单,那么查询:类似并查集一样的进行路径压缩,即如果rx[Val]被使用,那么rx[Val]=find(rx[Val]),对应修改rx_cnt[Val]即可,然后返回rx_cnt[Val]为x的值,y同样如此。
解决了这个问题,下面求解最小步数就很简单了。我们在纸上将i与pos[i]连上一条边,发现会构成很多个环,如果这个环中有0,那么直接把0按照环的反方向依次移动,即可把整个环都归位,如果环中没有0,那么先把0移进去,归位之后再移出来,步数+2即可,这样是最优的方案。证明可以使用置换群什么的。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;
const int MAXN=;
bool vis[MAXN];
int T,n,s,q,p,m,d,ans;
int c[MAXN],pos[MAXN],cnt[MAXN],rx[MAXN],ry[MAXN],rx_cnt[MAXN],ry_cnt[MAXN];
inline int gi(){int res; scanf("%d",&res); return res;}
int gcd(int A,int B)
{
if(A%B==)return B;
return gcd(B,A%B);
}
void insert(int x)
{
int tmp;
if((tmp=x+d)>=n)tmp-=n;
rx[x]=tmp;
rx_cnt[x]=;
x%=m;
if(--cnt[x])return;
if((tmp=x+)>=m)tmp-=m;
ry[x]=tmp;
ry_cnt[x]=;
}
int query(int *r,int *r_cnt,int x)
{
if(r[x]==x)return ;
r_cnt[x]=r_cnt[x] + query(r,r_cnt,r[x]);
r[x]=r[r[x]];
return r_cnt[x];
}
int main()
{
T=gi();
while(T--)
{
scanf("%d%d%d%d%d%d",&n,&s,&q,&p,&m,&d); pos[]=s;
for(int i=;i<n;i++) c[i]=((LL)c[i-]*q+p)%m;
d%=n;//insert()中没有使用取模,而是使用减法代替,所以这里先模一下。
m=gcd(n,d);
for(int i=;i<m;i++)
{
cnt[i]=n/m;
ry[i]=i;
ry_cnt[i]=;
}
for(int i=;i<n;i++) rx[i]=i,rx_cnt[i]=;
insert(pos[]);
for(int i=;i<n;i++)
{
int y=query(ry,ry_cnt,c[i]%m);
int x=query(rx,rx_cnt,(c[i]+y)%n);
pos[i]=((LL)d*x+y+c[i])%n;
insert(pos[i]);
}
ans=; memset(vis,,sizeof vis);
for(int i=;i<n;i++)
if(!vis[i])
{
int now=i,Start=i,flag=,cnt=;
do
{
vis[now]=; cnt++;
if(now==)flag=;
now=pos[now];
}while(now!=Start);
if(cnt>)
{
ans+=cnt-;
if(!flag)ans+=;
}
}
printf("%d\n",ans);
}
return ;
}
[HNOI2010] 物品调度 fsk的更多相关文章
- 【BZOJ1998】[HNOI2010]物品调度(并查集,模拟)
[BZOJ1998][HNOI2010]物品调度(并查集,模拟) 题面 BZOJ,为啥这题都是权限题啊? 洛谷 题解 先不管\(0\)位置是个空,把它也看成一个箱子.那么最终的答案显然和置换循环节的个 ...
- [HNOI2010]物品调度
题目描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostm ...
- P3207 [HNOI2010]物品调度
传送门 完了题目看错了--还以为所有的\(x,y\)都要一样--结果题解都没看懂-- 先考虑如果已经求出了所有的\(pos\)要怎么办,那么我们可以把\(0\)也看做是一个箱子,然后最后每个箱子都在一 ...
- [BZOJ1998][Hnoi2010]Fsk物品调度
[BZOJ1998][Hnoi2010]Fsk物品调度 试题描述 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号,一开 ...
- 【BZOJ 1998】 1998: [Hnoi2010]Fsk物品调度(双向链表+并查集+置换)
1998: [Hnoi2010]Fsk物品调度 Description 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置,从0到n-1依次编号 ...
- BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换
BZOJ_1998_[Hnoi2010]Fsk物品调度_并查集+置换 Description 现在找工作不容易,Lostmonkey费了好大劲才得到fsk公司基层流水线操作员的职位.流水线上有n个位置 ...
- 【BZOJ】1998: [Hnoi2010]Fsk物品调度
http://www.lydsy.com/JudgeOnline/problem.php?id=1998 题意: 给你6个整数$n,s,q,p,m,d$. 有$n$个位置和$n-1$个盒子,位置编号从 ...
- BZOJ 1998: [Hnoi2010]Fsk物品调度 [置换群 并查集]
传送门 流水线上有n个位置,从0到n-1依次编号,一开始0号位置空,其它的位置i上有编号为i的盒子.Lostmonkey要按照以下规则重新排列这些盒子. 规则由5个数描述,q,p,m,d,s,s表示空 ...
- 【BZOJ 1998】[Hnoi2010]Fsk物品调度 置换群+并查集
置换群的部分水得一比,据说是经典的置换群理论(然而我并不知道这理论是啥).重点就在于怎么求pos!!!容易发现这个东西是这样的:每次寻找pos,先在本环里找,找不到再往下一个环里找,直到找到为止……一 ...
随机推荐
- [Phoenix] 一、快速入门
Phoenix是一个开源的HBASE SQL层.Phoeinx可以用标准的JDBC API替代HBASE client API来创建表,插入和查询HBASE中的数据. Phoenix作为应用层和HBA ...
- XShell连接不了虚拟机
本机安装好虚拟机和centeros; 使用xshell连接: linux Could not connect to '127.0.0.1' (port 22): Connection failed. ...
- Package md5 implements the MD5 hash algorithm as defined in RFC 1321 base64
https://golang.google.cn/pkg/crypto/md5/ Go by Example 中文:Base64编码 https://books.studygolang.com/gob ...
- Django学习之站点缓存详解
本文和大家分享的主要是django缓存中站点缓存相关内容,一起来看看吧,希望对大家学习django有所帮助. 缓存整个站点,是最简单的缓存方法 在 MIDDLEWARE_CLASSES 中加入 “ ...
- jQuery——能够编辑的表格
版权声明:欢迎转载,请注明出处 https://blog.csdn.net/suneqing/article/details/26856635 今天学习了利用jQuery实现能够编辑的表格这个 ...
- 剑指Offer:调整数组顺序使奇数位于偶数前面【21】
剑指Offer:调整数组顺序使奇数位于偶数前面[21] 题目描述 输入一个整形数组,实现一个函数来调整该数组中数字的顺序,使得所有奇数位于数组的前半部分,所有偶数位于数组的后半部分. 解题分析 使用插 ...
- 基本动画、复合动画设置 平移、缩放、旋转、透明度 编码实现 xml实现
public class VAActivity extends Activity { private ImageView iv_animation; private TextView tv_anima ...
- 《编程之美》之如何控制CPU的暂用率固定在50%
<编程之美>第一章 让CPU暂用率听你指挥的粗糙实现,如何控制CPU的暂用率固定在50% #include <stdio.h> #include <Windows.h&g ...
- Linux下Redis C++操作的封装
安装和启动Redis服务...略!很粗糙的版本,待改进... Redis Client C++示例代码...略! /** * Time: 14-3-10 * File: RedisCache.h * ...
- Codeforces Round #398 (Div. 2) C. Garland —— DFS
题目链接:http://codeforces.com/contest/767/problem/C 题解:类似于提着一串葡萄,用剪刀剪两条藤,葡萄分成了三串.问怎样剪才能使三串葡萄的质量相等. 首先要做 ...