首先我们可以考虑一下 \(x\) 关于 \(y\) 的对称点的坐标,不难发现就是 \(x + 2 \times (y - x)\),那么期望的增量就会增加 \(2 \times (y - x)\)。不难发现我们可以令 \(dp_{i, j}\) 表示 \(j\) 第 \(i\) 次操作(即假设进行了 \(p\) 轮操作,当前是第 \(q\) 次操作,则 \(i = (p - 1) \times m + q\)),则会有转移:

\[dp_{i, a_q} += \frac{1}{2} \times 2 \times (dp_{i - 1, a_q - 1} - dp_{i - 1, a_q}) + \frac{1}{2} \times 2 \times (dp_{i - 1, a_q + 1} - dp_{i - 1, a_q})
\]

即:

\[dp_{i, a_q} += dp_{i - 1, a_q - 1} + dp_{i - 1, a_q + 1} - 2 \times dp_{a_q}
\]

可以发现第一维可以直接压去,则有转移 \(i = a_q\):

\[dp_i += dp_{i - 1} + dp_{i + 1} - 2 \times dp_i
\]

你会发现这个转移非常有特色,实际上可以将上式划成两个部分:

\[dp_i += (dp_{i + 1} - dp_i) - (dp_i - dp_{i - 1})
\]

你会发现这实际上是两个差分数在相加,令 \(f_i = dp_i - dp_{i - 1}\),即:

\[dp_i = f_{i + 1} - f_i
\]

显然这样算是非常不方便的,我们干脆考虑差分数组 \(f\) 的变化,则有:

\[f_i += f_{i + 1} - f_i \Leftrightarrow f_i = f_{i + 1}
\]
\[f_{i + 1} -= f_{i + 1} - f_i \Leftrightarrow f_{i + 1} = f_i
\]

相当于将差分数组 \(f_i, f_{i + 1}\) 交换!那么问题转化为,给你一个序列,有 \(K\) 轮变换,每次变换有 \(m\) 次操作,按照给定的操作序列 \(a_i\) 交换 \(f_{a_i}, f_{a_i + 1}\)。因为每轮变换的操作序列都是一样的,这意味着每个位置在一轮之后变到的位置是一样的。于是我们先暴力将经过一轮操作后位置排列 \(P\) 变换到的位置序列 \(P'\)(事实上我们成排列 \(P \rightarrow P'\) 的这样一个过程叫做置换),对于置换而言一个常见的想法就是对 \(P_i \rightarrow P'_i\) 连一条边,这样将形成一张若干个简单环组成的有向图。那么每个位置经过 \(K\) 轮置换后的位置就相当于它在这个简单环上走 \(K\) 步后的位置,这个就很容易可以算出来了。

可以发现,上面这个做法的复杂度是 \(O(n + m)\) 的,非常地优秀!

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define rep(i, l, r) for(int i = l; i <= r; ++i)
const int N = 100000 + 5;
bool book[N];
int n, m, k, tmp, cnt, a[N], d[N], p[N], dp[N], nxt[N], ans[N];
vector <int> G[N];
int read(){
char c; int x = 0, f = 1;
c = getchar();
while(c > '9' || c < '0'){ if(c == '-') f = -1; c = getchar();}
while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
signed main(){
n = read();
rep(i, 1, n) d[i] = read(), p[i] = i, dp[i] = d[i] - d[i - 1];
m = read(), k = read();
rep(i, 1, m) a[i] = read(), swap(p[a[i]], p[a[i] + 1]);
rep(i, 1, n) nxt[i] = p[i];
rep(i, 1, n) if(!book[i]){
int x = i; G[++cnt].push_back(i), book[i] = true;
while(nxt[x] != i) x = nxt[x], book[x] = true, G[cnt].push_back(x);
}
rep(i, 1, cnt){
int S = G[i].size(), tr = k % S;
rep(j, 0, S - 1) ans[G[i][j]] = dp[G[i][(j + tr) % S]];
}
rep(i, 1, n) tmp += ans[i], printf("%lld.0\n", tmp);
return 0;
}

AT2164 [AGC006C] Rabbit Exercise的更多相关文章

  1. [AT2164] [agc006_c] Rabbit Exercise

    题目链接 AtCoder:https://agc006.contest.atcoder.jp/tasks/agc006_c 洛谷:https://www.luogu.org/problemnew/sh ...

  2. 【做题】agc006C - Rabbit Exercise——模型转换

    原文链接https://www.cnblogs.com/cly-none/p/9745177.html 题意:数轴上有\(n\)个点,从\(1\)到\(n\)编号.有\(m\)个操作,每次操作给出一个 ...

  3. AGC006C Rabbit Exercise

    传送门 设 \(f_{i,j}\) 表示兔子 \(i\) 在当前 \(j\) 轮的期望位置 对于一次操作 \(f_{i,j+1}=\frac{1}{2}(2f_{i-1,j}-f_{i,j})+\fr ...

  4. 【agc006C】Rabbit Exercise

    Portal --> agc006C Solution 啊感觉是好有意思的一道题qwq官方题解里面的说辞也是够皮的哈哈哈..(大概就是说如果你没有意识到那个trick的话这题这辈子都做不出来qw ...

  5. 【AGC006C】Rabbit Exercise 置换

    题目描述 有\(n\)只兔子站在数轴上.为了方便,将这些兔子标号为\(1\ldots n\).第\(i\)只兔子的初始位置为\(a_i\). 现在这些兔子会按照下面的规则做若干套体操.每一套体操由\( ...

  6. AT2164 Rabbit Exercise

    传送门 解题思路 首先考虑k=1的情况,对于每一个a[i],它可能会到a[i-1]*2-a[i] 与 a[i+1]*2-a[i]两个位置,概率都为%50,那么它的期望位置为 (a[i-1]*2-a[i ...

  7. 【AtCoder】【思维】【置换】Rabbit Exercise

    题意: 有n只兔子,i号兔子开始的时候在a[i]号位置.每一轮操作都将若干只兔子依次进行操作: 加入操作的是b[i]号兔子,就将b[i]号兔子移动到关于b[i]-1号兔子现在所在的位置对称的地方,或者 ...

  8. AtCoder Grand Contest 006 (AGC006) C - Rabbit Exercise 概率期望

    原文链接https://www.cnblogs.com/zhouzhendong/p/AGC006C.html 题目传送门 - AGC006C 题意 有 $n$ 个兔子,从 $1$ 到 $n$ 编号, ...

  9. [Atcoder Grand 006 C] Rabbit Exercise 解题报告 (期望)

    题目链接:https://www.luogu.org/problemnew/show/AT2164 https://agc006.contest.atcoder.jp/tasks/agc006_c 题 ...

随机推荐

  1. Generating Adversarial Examples with Adversarial Networks

    目录 概 主要内容 black-box 拓展 Xiao C, Li B, Zhu J, et al. Generating Adversarial Examples with Adversarial ...

  2. matplotlib 进阶之Tight Layout guide

    目录 简单的例子 Use with GridSpec Legend and Annotations Use with AxesGrid1 Colorbar 函数链接 matplotlib教程学习笔记 ...

  3. [opencv]KAZE、AKAZE特征检测、匹配与对象查找

    AkAZE是KAZE的加速版 与SIFT,SUFR比较: 1.更加稳定 2.非线性尺度空间 3.AKAZE速度更加快 4.比较新的算法,只有Opencv新的版本才可以用 AKAZE局部匹配介绍 1.A ...

  4. 基于Spring MVC + Spring + MyBatis的【网上购物系统】

    资源下载:https://download.csdn.net/download/weixin_44893902/45601185 练习点设计:修改.删除 一.语言和环境 实现语言:JAVA语言. 环境 ...

  5. nalu,在java中使用lambda查询数据库

    不忘初心 最开始接触写代码的时候,用的是C井,查数据库直接硬编码sql,挺难受的. 后来学习到EntityFramework,用起来是真香,都是强类型,各种智能提示,代码写起来极度舒适,效率起飞. 最 ...

  6. 初识python 之 爬虫:使用正则表达式爬取“古诗文”网页数据

    通过requests.re(正则表达式) 爬取"古诗文"网页数据. 详细代码如下: #!/user/bin env python # author:Simple-Sir # tim ...

  7. 初识python: 字典

    使用数据字典,编写一个多级菜单: 需求:每一级可返回上级,可退出. 多级菜单 #!/user/bin env python # author:Simple-Sir # time:20180915 # ...

  8. VMware_win10能ping通虚拟机ip,虚拟机ping不通win10ip的解决方法

    一.虚拟机设置为桥接模式 二.修改虚拟机linux的ip 查看win10的ip和网关 使用ifconfig查看网卡名,并在 /etc/sysconfig/network-scripts/目录修改对应的 ...

  9. Centos更换阿里云源

    1.备份 mv /etc/yum.repos.d/CentOS-Base.repo /etc/yum.repos.d/CentOS-Base.repo.backup 2.下载新的CentOS-Base ...

  10. 【Java】成员变量赋值执行顺序

    程序中成员变量赋值的执行顺序