zoukankan      html  css  js  c++  java
  • CodeForces 258D Little Elephant and Broken Sorting(期望)

    CF258D Little Elephant and Broken Sorting

    题意

    题意翻译

    有一个(1sim n)的排列,会进行(m)次操作,操作为交换(a,b)。每次操作都有(50\%)的概率进行。

    求进行(m)次操作以后的期望逆序对个数。

    (n,mle 1000)

    输入输出格式

    输入格式:

    The first line contains two integers (n) and (m) ((1leq n,mleq 1000,n>1)) — the permutation size and the number of moves. The second line contains (n) distinct integers, not exceeding (n) — the initial permutation. Next (m) lines each contain two integers: the (i)-th line contains integers (a_{i}) and (b_{i}) ((1leq a_{i},b_{i}leq n,a_{i} eq b_{i})) — the positions of elements that were changed during the (i)-th move.

    输出格式:

    In the only line print a single real number — the answer to the problem. The answer will be considered correct if its relative or absolute error does not exceed (10^{-6}).

    输入输出样例

    输入样例#1:

    2 1
    1 2
    1 2
    

    输出样例#1:

    0.500000000
    

    输入样例#2:

    4 3
    1 3 2 4
    1 2
    2 3
    1 4
    

    输出样例#2:

    3.000000000
    

    思路

    这道题真的水。 --Mercury

    完全想不到的状态设计,感谢(Mercury)巨佬的指点。

    定义(f(i,j))为位置(i)上的数比位置(j)上的数大的概率。假设每次交换都是(100\%)成功的,不妨设这次交换的数的下标为(a,b),那么对于任意的(f(i,a),f(i,b))就要被交换,(f(a,i),f(b,i))也要被交换。可是当前交换的概率是(50\%)的,所以(f(i,a),f(i,b))之间的差值要被分别减少(50\%),也就相当于(f(i,a)=f(i,b)=(f(i,a)+f(i,b))div 2)。同理,(f(a,i)=f(b,i)=(f(a,i)+f(b,i))div 2)。最后的逆序对期望,也就是(Sigma [i<j]f(i,j) imes 1),也就是(Sigma [i<j]f(i,j))

    还要再胡扯两句。 其实只要想出了(f(i,j))这个东西,什么都简单了,可是又会有几个人能够想到这种方法呢?完全没有类似的情况作为参考,掌握了这道题却又能给类似的题提供经验(毕竟也没有类似的题)。下一次见到了这种思维量大的题,还是不太能想得出。思维的活跃在(OI)中还是有很大的作用的啊!

    AC代码

    #include<bits/stdc++.h>
    #define RG register
    using namespace std;
    int n,m,a[1005];
    double ans,f[1005][1005];
    int read()
    {
        RG int re=0;RG char ch=getchar();
        while(!isdigit(ch)) ch=getchar();
        while(isdigit(ch)) re=(re<<3)+(re<<1)+ch-'0',ch=getchar();
        return re;
    }
    int main()
    {
        n=read(),m=read();
        for(RG int i=1;i<=n;i++) a[i]=read();
        for(RG int i=1;i<=n;i++)
            for(RG int j=i+1;j<=n;j++)
                if(a[i]>a[j]) f[i][j]=1.0;
                else f[j][i]=1.0;
        while(m--)
        {
            RG int x=read(),y=read();
            if(x==y) continue;
            for(RG int i=1;i<=n;i++)
            {
                if(i==x||i==y) continue;
                f[i][x]=f[i][y]=(f[i][x]+f[i][y])/2;
                f[x][i]=f[y][i]=(f[x][i]+f[y][i])/2;
            }
            f[x][y]=f[y][x]=0.5;
        }
        for(RG int i=1;i<=n;i++)
            for(RG int j=i+1;j<=n;j++)
                ans+=f[i][j];
        printf("%.8f",ans);
        return 0;
    }
    
  • 相关阅读:
    Java设计模式-装饰器模式
    【c++内存分布系列】单独一个类
    【转】LCS
    快速排序
    冒泡排序
    选择排序
    多线程读取全局变量
    【转】一致性hash算法(consistent hashing)
    【转】五笔的字典序编码与解码
    给定一个函数rand()能产生0到n-1之间的等概率随机数,问如何产生0到m-1之间等概率的随机数?
  • 原文地址:https://www.cnblogs.com/coder-Uranus/p/9899145.html
Copyright © 2011-2022 走看看