[AGC006C] Rabbit Exercise

题意

传送门

\(n\) 只兔子进行 \(k\) 轮跳跃,每轮跳跃由 \(m\) 只兔子 \(a_1,\dots,a_m\) 按顺序完成。

定义对于兔子 \(x_i\) 一次跳跃为随机选择标号(标号并不随着位置改变而改变)为 \(i-1\)\(i+1\) 中的一只做镜像对称。

求最终每只兔子的期望位置。

\(n,m \le 10^5,k \le 10^{18}\)

思路

详见

期望题都好神啊

通过一些观察会发现,好像相邻两只编号兔子间的距离一直都是这么一些数。

发现差分后每一次操作即将两个差互换,于是可以用倍增算出每个差最后在哪里,最后复原即可。

#include <bits/stdc++.h>
const int N=100005,W=60;
int n,a[N],d[N],m,f[N][61],t[N],x;
long long k;
int main(){
	scanf("%d",&n);
	for (int i=1;i<=n;i++) scanf("%d",&a[i]);
	scanf("%d%lld",&m,&k);
	for (int i=1;i<=n;i++) d[i]=i;
	for (int i=1;i<=m;i++){
		scanf("%d",&x);
		std::swap(d[x],d[x+1]);
	}
	for (int i=1;i<=n;i++) f[i][0]=d[i];
	for (int i=1;i<=W;i++)
		for (int j=1;j<=n;j++)
			f[j][i]=f[f[j][i-1]][i-1];
	for (int i=W;i>=0;i--)
	if ((k-1)&(1ll<<i)){
		for (int j=1;j<=n;j++)
			 t[j]=d[f[j][i]];
		memcpy(d,t,sizeof(d));
	}
		
	long long x=a[1];
	printf("%lld\n",x);
	for (int i=2;i<=n;i++){
		x=x+a[d[i]]-a[d[i]-1];
		printf("%lld\n",x);
	}
}

后记

别忘了开ll

posted @ 2020-12-30 09:47  flyfeather  阅读(106)  评论(0编辑  收藏  举报