正题
题目链接:https://www.luogu.com.cn/problem/AT2164
题目大意
nnn只兔子编号为1∼n1\sim n1∼n,第iii只在坐标轴xix_ixi处。然后mmm次跳跃,每次给出aia_iai,编号为aia_iai的兔子会等概率的选取ai−1a_{i-1}ai−1和ai+1a_{i+1}ai+1跳跃到对称位置。进行kkk轮,求最后每只兔子的期望位置。
3≤n≤105,1≤m≤105,1≤k≤10183\leq n\leq 10^5,1\leq m\leq 10^5,1\leq k\leq 10^{18}3≤n≤105,1≤m≤105,1≤k≤1018
解题思路
设fif_ifi表示iii的期望位置的话,对于每次跳跃兔子xxx,它的概率就是
fx=(2fx−1−fx)+(2fx+1−fx)2=fx−1+fx+1−fxf_x=\frac{(2f_{x-1}-f_{x})+(2f_{x+1}-f_x)}{2}=f_{x-1}+f_{x+1}-f_{x}fx=2(2fx−1−fx)+(2fx+1−fx)=fx−1+fx+1−fx
然后这个见到这个式子就直接差分成gi=fi−fi−1g_i=f_i-f_{i-1}gi=fi−fi−1。
然后上面那个东西就变成了交换iii和i+1i+1i+1。
然后就是给一个交换,交换kkk次,因为kkk很大倍增搞就好了。
时间复杂度O(nlogk)O(n\log k)O(nlogk)
code
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
const ll N=1e5+10;
ll n,m,k,d[N],ans[N],t[N];
double x[N];
signed main()
{scanf("%lld",&n);for(ll i=1;i<=n;i++){scanf("%lf",&x[i]);d[i]=ans[i]=i;}scanf("%lld%lld",&m,&k);for(ll i=1;i<=m;i++){ll x;scanf("%lld",&x);swap(d[x],d[x+1]);}while(k){if(k&1){for(ll i=1;i<=n;i++)t[i]=ans[d[i]];for(ll i=1;i<=n;i++)ans[i]=t[i];}for(ll i=1;i<=n;i++)t[i]=d[d[i]];for(ll i=1;i<=n;i++)d[i]=t[i];k>>=1;}double sum=0;for(ll i=1;i<=n;i++){sum+=x[ans[i]]-x[ans[i]-1];printf("%.1lf\n",sum);}return 0;
}