rabbit 等概率跳,先导一波期望值?
等一下:
发现
E
(
i
)
=
0.5
∗
(
E
(
i
+
1
)
−
E
(
i
)
)
+
0.5
∗
(
E
(
i
−
1
)
−
E
(
i
)
)
E(i)=0.5*(E(i+1)-E(i))+0.5*(E(i-1)-E(i))
E(i)=0.5∗(E(i+1)−E(i))+0.5∗(E(i−1)−E(i))
即
一
次
操
作
可
以
往
i
+
1
跳
,
也
可
以
往
i
−
1
跳
\color{red}即一次操作可以往i+1跳,也可以往i-1跳
即一次操作可以往i+1跳,也可以往i−1跳
E
(
i
)
表
示
第
i
只
兔
子
经
过
1
次
跳
跃
后
的
期
望
位
置
\color{brown} E(i)表示第i只兔子经过1次跳跃后的期望位置
E(i)表示第i只兔子经过1次跳跃后的期望位置
化简一下得E(i)=E(i+1)+E(i-1)-E(i)
可得
E
(
i
)
\color{blue} E(i)
E(i)-E(i-1)= E(i+1)-E(i) ,我们可以考虑差分
P
.
S
蓝
色
的
E
(
i
)
是
更
新
后
的
E
(
i
)
P.S 蓝色的E(i)是更新后的E(i)
P.S蓝色的E(i)是更新后的E(i)
即将E(i+1)-E(i)的值附在E(i)-E(i-1)
定义
Y
(
k
)
=
E
(
k
)
−
E
(
k
−
1
)
Y(k)=E(k)-E(k-1)
Y(k)=E(k)−E(k−1)
则一次更新就是将Y(k+1)附在Y(k)上,但当
Y
(
k
+
1
)
赋
在
Y
(
k
)
时
,
由
于
差
分
数
组
被
破
坏
Y(k+1)赋在Y(k)时,由于差分数组被破坏
Y(k+1)赋在Y(k)时,由于差分数组被破坏
所以Y(k+1)也应被更新
所以我们swap(y[k+1],y[k])就能完成一次操作
但这样时间复杂度过高, K < = 1 e 18 K<=1e18 K<=1e18
——————————————————————————————————————————————
考虑优化
我们发现操作必定构成环。
证
明
:
\color{green}证明:
证明:
如果操作不构成环,则设不构成环的一条链S
那么S上的操作必定只能从链的一段入一段出,那么这条链上的数会越来越多,显然不可能,矛盾。
——————————————————————————————————————————————
那么我们只要预处理出所有的环,记录长度,对每条环的点单独处理即可
预
处
理
:
\color{red}预处理:
预处理:
void dfs(int st){
while(!vis[st])
{
id[++cnt]=st;
vis[st]=1;
st=nxt[st];
}
return;
}
——————————————————————————————————————————————
P.S:
差分的前缀和等于前缀和的差分等于原串
——————————————————————————————————————————————
AC代码:
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=100010;
ll k;
int n,m,id[N];
ll x[N];int nxt[N];ll cf[N],ans[N];bool vis[N];int cnt;
void dfs(int st){
while(!vis[st])
{
id[++cnt]=st;
vis[st]=1;
st=nxt[st];
}
return;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld",&x[i]);
cf[i]=x[i]-x[i-1];
nxt[i]=i;
}
scanf("%d%lld",&m,&k);
for(int i=1;i<=m;i++){
int kk;
scanf("%d",&kk);
swap(nxt[kk],nxt[kk+1]);
}
for(int i=1;i<=n;i++){
if(!vis[i]){
cnt=0;
dfs(i);
if(cnt==1) ans[id[1]]=cf[id[1]];
else {
for(int j=1;j<=cnt;j++){
ans[id[j]]=cf[id[(k+j-1)%cnt+1]];//一定要从右边赋值到左边
}
}
}
}
ll anss=0;
for(int i=1;i<=n;i++){
anss+=ans[i];
printf("%lld.0\n",anss);
}
}
重要部分
ans[id[j]]=cf[id[(k+j-1)%cnt+1]];
一定要先减1在加1
应为取模cnt的值域是[0,cnt),而我们需要的值域是[1,cnt]