
[2018省队模拟]简单模拟
发布日期:2021-05-04 16:53:08
浏览次数:24
分类:原创文章
本文共 2545 字,大约阅读时间需要 8 分钟。
题目链接
思路
题目条件很玄学,要找出值为 bi b i 的元素与 1 1 位置的元素交换。
为了防止到处找元素,我们把每个元素在哪个位置记下来,记录 为值为 i i 的元素的位置。
这样,题目就变成了:把 数组中的位置 bi b i 的元素与值为 1 1 的元素交换(方便起见,把这样的交换记作 )。
现在,我们只要关心值为 1 1 的元素的位置。
我们研究研究对 数组交换的性质:
性质 1 1 : 后, 1 1 的位置变成了 。
证明:这个结论是很显然的,没有证明。
性质 1.5 1.5 :经过一连串的 swap(b1),swap(b2),⋯,swap(bq) s w a p ( b 1 ) , s w a p ( b 2 ) , ⋯ , s w a p ( b q ) 后, 1 1 的位置变成了 。
证明:由性质 1 1 得到。
性质 :如果经过一轮交换, p p 数组中 位置的值到了 si s i 上,若有 s1=1 s 1 = 1 ,那么现在再次进行同样的交换,这个值会到 ssi s s i 上。
证明:交换的是位置,因此第一次交换后可以把这个数组视为原数组。
根据推论 1.5 1.5 和性质 2 2 ,按照 数组的顺序,进行两轮交换后,可以根据性质 2 2 来快速计算后面的变换情况。
具体流程:
- 按照 数组的顺序进行两轮交换;
- 计算出上面性质 2 2 中提到的 值;
- 利用快速幂,计算出前 ⌊nq⌋ ⌊ n q ⌋ 项的值;
- 最后暴力计算出最后 nmodq n mod q 项的值。
代码
#include <cstdio>#include <cstring>#include <algorithm>const int maxn=200000;int n,q;long long m;struct per{ int a[maxn+10]; per operator *(const per &other) const { per res; for(register int i=1; i<=n; ++i) { res.a[i]=other.a[a[i]]; } return res; }};int a[maxn+10],b[maxn+10],p[maxn+10],opos,tmp[maxn+10];per now,res;int read(){ int x=0,f=1; char ch=getchar(); while((ch<'0')||(ch>'9')) { if(ch=='-') { f=-f; } ch=getchar(); } while((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f;}int jump(int *ar,int t){ for(register int i=1; i<=t; ++i) { std::swap(ar[opos],ar[b[(i-1)%q+1]]); opos=b[(i-1)%q+1]; } return 0;}int main(){ n=read(); q=read(); scanf("%I64d",&m); for(register int i=1; i<=n; ++i) { a[i]=read(); } for(register int i=1; i<=q; ++i) { b[i]=read(); } for(register int i=1; i<=n; ++i) { p[a[i]]=i; } opos=a[1]; if(m<=2*q) { jump(p,m); for(register int i=1; i<=n; ++i) { tmp[p[i]]=i; } for(register int i=1; i<n; ++i) { printf("%d ",tmp[i]); } printf("%d\n",tmp[n]); return 0; } jump(p,q); memcpy(tmp,p,sizeof p); jump(p,q); for(register int i=1; i<=n; ++i) { now.a[tmp[i]]=p[i]; } for(register int i=1; i<=n; ++i) { res.a[i]=i; } long long t=m/q-2; while(t) { if(t&1) { res=res*now; } t>>=1; now=now*now; } now=res; for(register int i=1; i<=n; ++i) { p[i]=now.a[p[i]]; } jump(p,m%q); for(register int i=1; i<=n; ++i) { tmp[p[i]]=i; } for(register int i=1; i<n; ++i) { printf("%d ",tmp[i]); } printf("%d\n",tmp[n]); return 0;}
发表评论
最新留言
关注你微信了!
[***.104.42.241]2025年04月04日 23时55分12秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!
推荐文章
环境配置 jdk_mysql_myeclipse8.6
2019-03-05
Session验证码的实现(2018-7-3)
2019-03-05
spring启动错误:Could not resolve placeholder
2019-03-05
JavaWeb---实现JavaBean来接收参数、请求转发、域对象
2019-03-05
瀚高数据库中 java代码类型与bit对应(APP)
2019-03-05
选择性估算器绕过行安全策略漏洞
2019-03-05
对PostgreSQL数据库结构的宏观理解
2019-03-05
查询某表格上次进行vacuum的时间
2019-03-05
invalid byte sequence for encoding
2019-03-05
failed to initialize the database
2019-03-05
invalid byte sequence for encoding
2019-03-05
ArduPilot源码极速下载手册(一文告别github慢速问题)
2019-03-05
聊一聊那些应该了解的大佬(飞控,人工智能方向)
2019-03-05
redis向数组中添加值并查看数组长度
2019-03-05
python3基础梳理11python中模块和包
2019-03-05
JS编写一个函数,计算三个不同数字的大小,按从小到大顺序打印(穷举法)
2019-03-05
mybatis中like的注意
2019-03-05
sqlplus的基本使用
2019-03-05
oracle删除表重复数据
2019-03-05
Oracle删除主表数据
2019-03-05