[AGC006C] Rabbit Exercise

link

题目翻译

数轴上有 $n$ 个点,每次可以选择点 $x$ ,从 $x-1$ 或 $x+1$ 中等概率选择一个点,作关于此点的对称点,共 $k$ 轮,问每个点所在位置的期望。

$solution:$

若此刻选择 $i$ 点移动,设 $f_i$ 表示 $i$ 点的期望,则 $f_i=f_{i-1}+f_{i+1}-f_i$ ,暴力 $dp$ ,时间复杂度 $O(nk)$ ,无法通过此题。

考虑差分,设 $d_i=f_i-f_{i-1}$ ,若 $i$ 点移动后, $d_i=f_i-f_{i-1}=f_{i-1}+f_{i+1}-f_i-f_{i-1}=f_{i+1}-f_{i}\\d_{i+1}=f_{i+1}-f_i=f_{i+1}-(f_{i-1}+f_{i+1}-f_i)=f_i-f_{i+1}$ 。

所以当 $i$ 点移动的本质是交换 $d_i,d_{i+1}$ ,设 $g_{i,j}$ 表示 $i$ 号经过 $2^j$ 次后的差分数组,直接倍增维护即可。

时间复杂度 $O(\log k)$

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define int long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=100001;
int m,k,ans,n,x[MAXN],d[MAXN],a[MAXN],fa[MAXN][61],p[MAXN];
signed main(){
//    freopen("2.in","r",stdin);
    n=read();
    for(int i=1;i<=n;i++) x[i]=read(),d[i]=i,p[i]=x[i]-x[i-1];
    m=read(),k=read();
    for(int i=1;i<=m;i++) a[i]=read(),swap(d[a[i]],d[a[i]+1]);
    for(int i=1;i<=n;i++) fa[i][0]=d[i];
    for(int j=1;j<=60;j++)
        for(int i=1;i<=n;i++) fa[i][j]=fa[fa[i][j-1]][j-1];
    for(int i=1;i<=n;i++){
        int res=i;
        int K=k;
        for(int j=60;j>=0;j--) if(K-(1ll<<j)>=0) K-=(1ll<<j),res=fa[res][j];
        ans+=p[res];
        printf("%.1f\n",(double)ans);
    }return 0;
}/*
3
1 -1 1
2 2
2 2
*/
View Code

 

posted @ 2019-07-17 10:27  siruiyang_sry  阅读(163)  评论(0编辑  收藏  举报