zoukankan      html  css  js  c++  java
  • AT2164[AGC006C]Rabbit Exercise【差分,倍增,数学期望】

    正题

    题目链接:https://www.luogu.com.cn/problem/AT2164


    题目大意

    \(n\)只兔子编号为\(1\sim n\),第\(i\)只在坐标轴\(x_i\)处。然后\(m\)次跳跃,每次给出\(a_i\),编号为\(a_i\)的兔子会等概率的选取\(a_{i-1}\)\(a_{i+1}\)跳跃到对称位置。进行\(k\)轮,求最后每只兔子的期望位置。

    \(3\leq n\leq 10^5,1\leq m\leq 10^5,1\leq k\leq 10^{18}\)


    解题思路

    \(f_i\)表示\(i\)的期望位置的话,对于每次跳跃兔子\(x\),它的概率就是

    \[f_x=\frac{(2f_{x-1}-f_{x})+(2f_{x+1}-f_x)}{2}=f_{x-1}+f_{x+1}-f_{x} \]

    然后这个见到这个式子就直接差分成\(g_i=f_i-f_{i-1}\)

    然后上面那个东西就变成了交换\(i\)\(i+1\)

    然后就是给一个交换,交换\(k\)次,因为\(k\)很大倍增搞就好了。

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


    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;
    }
    
  • 相关阅读:
    Python的传递引用
    kafka的ACK
    分布式事务
    Java中的锁
    docker笔记
    MySQL数据库优化
    Centos7使用yum命令安装Mysql5.6.X
    ubuntu16.04安装workbench
    ubuntu下IDEA配置tomcat报错Warning the selected directory is not a valid tomcat home
    ubuntu配置JDK
  • 原文地址:https://www.cnblogs.com/QuantAsk/p/14483029.html
Copyright © 2011-2022 走看看