SRM 664 Div2 Hard: BearSortsDiv2(归并排序)

Problem Statement

 

Bear Limak was chilling in the forest when he suddenly found a computer program. The program was a correct implementation of MergeSort. Below you can find the program in pseudocode.


# mergeSort(left,right) sorts elements left, left+1, ..., right-1 of a global array T
function mergeSort(left,right):
    # if there is at most one element, we are done
    if left+1 >= right: return

    # otherwise, split the sequence into halves, sort each half separately
    mid = (left + right) div 2
    mergeSort(left,mid)
    mergeSort(mid,right)

    # then merge the two halves together
    merged = []    # an empty sequence
    p1 = left
    p2 = mid
    while (p1 < mid) or (p2 < right):
        if p1 == mid:
            merged.append( T[p2] )
            p2 += 1
        else if p2 == right:
            merged.append( T[p1] )
            p1 += 1
        else:
                        if(pos[a[p1]] < pos[a[p2]]) tmp.push_back(a[p1++]);
                        else tmp.push_back(a[p2++]);
    # finally, move the merged elements back into the original array
    for i from left to right-1 inclusive:
        T[i] = merged[i-left]

Limak noticed that one part of the implementation was missing: the function LESS. You can probably guess that the function is supposed to return a boolean value stating whether the first argument is less than the second argument. However, Limak is a bear and he didn't know that. Instead he implemented his own version of this function. Limak's function uses a true random number generator. Each of the two possible return values (true, false) is returned with probability 50 percent.


The random values generated in different calls to Limak's function LESS are mutually independent. Note that even if you call LESS twice with the same arguments, the two return values may differ.


After implementing LESS, Limak decided to run his brand new program. He initialized the global array T to contain N elements. Then, he filled the values 1 through N into the array: for each valid i, he set T[i] to i+1. Finally, he executed the function mergeSort(0,N).


Even with Limak's new LESS function, the program never crashes. On the other hand, it does not necessarily produce a sorted sequence when it terminates. In general, when the program terminates, the array T will contain some permutation of the numbers 1 through N.


After running the program many times, Limak has noticed that different output permutations are produced with different probabilities. Your task is to help him learn more about these probabilities. More precisely, your task is to compute the probability that a given sequence will appear as the output of Limak's program.


You are given a vector <int> sortedSequence with N elements, containing a permutation of 1 through N. Let P be the probability that Limak's program, when run on an array with N elements, outputs this permutation. Return the value log(P), where log denotes the natural (base e) logarithm.

Definition

 
Class: BearSortsDiv2
Method: getProbability
Parameters: vector <int>
Returns: double
Method signature: double getProbability(vector <int> seq)
(be sure your method is public)

Limits

 
Time limit (s): 2.000
Memory limit (MB): 256
Stack limit (MB): 256

Notes

- Your return value must have absolute or relative error smaller than 1e-9.
- You may assume that for each N and for each permutation P of 1 through N the probability that P appears as the output of Limak's program is strictly positive.

Constraints

- sortedSequence will contain exactly N elements.
- N will be between 1 and 40, inclusive.
- Elements of sortedSequence will be between 1 and N, inclusive.
- Elements of sortedSequence will be pairwise distinct.



题目大意:

归并排序过程中,“归并”这步是:

                        if( isless(a[p1]],a[p2]) ) tmp.push_back(a[p1++]);
                        else tmp.push_back(a[p2++]);

isless()函数等概率返回真假。

求最后归并得到某一给定的数列的概率是多少

(输出log(概率))


思路:

归并是决定两个数之间的顺序,已知给定数列,显然只有一种归并方式

所以再模拟一遍归并排序就能算出概率


//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <cstring>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <string>
#include <vector>
#include <cstdio>
#include <ctime>
#include <bitset>
#include <algorithm>
#define SZ(x) ((int)(x).size())
#define ALL(v) (v).begin(), (v).end()
#define foreach(i, v) for (__typeof((v).begin()) i = (v).begin(); i != (v).end(); ++ i)
#define REP(i,n) for ( int i=1; i<=int(n); i++ )
using namespace std;
typedef long long ll;
#define X first
#define Y second
typedef pair<int,int> pii;

const int N = 1e3+100;
int pos[N];
vector<int>tmp;
int a[N];
double ans = 0;
void Merge(int l,int r){
        if( l+1 >= r) return ;
        int m = (l+r)>>1;
        Merge(l,m),Merge(m,r);
        int p1 = l, p2 = m;
        while(p1 < m || p2 < r){
                if(p1 == m) tmp.push_back(a[p2++]);
                else if(p2 == r) tmp.push_back(a[p1++]);
                else{
                        ans += log(0.5);//log(a*b) = loga + logb
                        if(pos[a[p1]] < pos[a[p2]]) tmp.push_back(a[p1++]);
                        else tmp.push_back(a[p2++]);
                }
        }
        foreach(it,tmp) a[l++] = *it;
        tmp.clear();
}

class BearSortsDiv2 {
public:
   double getProbability( vector <int> seq ) {
        int top = 0;
        ans = 0;
        foreach(it,seq){
                a[top] = top+1;
                pos[*it] = top++;
        }
        Merge(0,SZ(seq));
        return ans;
   }
};



你可能感兴趣的:(SRM 664 Div2 Hard: BearSortsDiv2(归并排序))