标签:链表+数论知识。

题解:

  对于这道题,其实就是两个问题的拼凑,我们分开来看。
  首先要求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 ;
}

最新文章

  1. 电脑安装Android4.0虚拟机的做法
  2. c++中有些重载运算符为什么要返回引用
  3. js_css_dl.dt实现列表展开、折叠效果
  4. [爬虫学习笔记]Url过滤模块UrlFilter
  5. sql思维
  6. Python标准库10 多进程初步 (multiprocessing包)
  7. hdu 3537 Daizhenyang&#39;s Coin 博弈论
  8. 数据结构练习 02-线性结构2. Reversing Linked List (25)
  9. LLDB中的小技巧
  10. Elasticsearch和MongoDB分片及高可用对比
  11. ajaxfileupload批量上传文件+图片尺寸限制
  12. hiho第151周 Building in Sandbox floodfill
  13. RHEL 6.9 udev 将lv绑定raw devices
  14. angular post 带参数 导出excel
  15. 在Ubuntu 16.04下安装nodejs
  16. 算法相关——Java排序算法之桶排序(一)
  17. JS中函数表达式与函数声明的区别
  18. Writing modular applications with laravel-modules
  19. MySQL基础之 AUTO_INCREMENT
  20. SQL Server XML变量转为Json文本

热门文章

  1. 基于XML配置的Sping AOP详解
  2. 从 Spring Cloud 看一个微服务框架的「五脏六腑」(转)
  3. C++ Lambda表达式和仿函数笔记
  4. 电脑插入U盘后显示CD驱动器,如何还原为正常U盘?
  5. 前端photoshop 切图神器cutterman
  6. Express中的Ejs模板传值问题
  7. delphi2010\delphi XE7 开发及调试WebService 实例
  8. jquery特效(8)—倒计时
  9. Educational Codeforces Round 2 C. Make Palindrome —— 贪心 + 回文串
  10. 基于BASYS2的VHDL程序——数字钟(改进版)