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;
   }
};

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-04 22:20:18

SRM 664 Div2 Hard: BearSortsDiv2(归并排序)的相关文章

topcpder SRM 664 div2 A,B,C BearCheats eyesight x BearPlays equalPiles x BearSorts getProbability

A题,熊孩子测视力,水题,题意就是判断一下两个数对应位不相同的数字有多少个. #include<bits/stdc++.h> using namespace std; class BearCheats{ public: string eyesight(int A, int B){ int digA[42],digB[42]; int t = 0; while(A){ digA[t++] = A%10; A/=10; } for(int i = 0; i < t; i++){ digB[i

TC SRM 664 div2 AB

#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; class BearCheats{ public: string eyesight(int A, int B){ char t[256]; string s1; sprintf(t, "%d", A); s1 = t; string s2; cha

TC SRM 664 div2 B BearPlaysDiv2 bfs

BearPlaysDiv2 Problem Statement    Limak is a little bear who loves to play. Today he is playing by moving some stones between three piles of stones. Initially, the piles contain A, B, and C stones, respectively. Limak's goal is to produce three equa

topcoder SRM 618 DIV2 WritingWords

只需要对word遍历一遍即可 int write(string word) { int cnt = 0; for(int i = 0 ; i < word.length(); ++ i){ cnt+=word[i]-'A'+1; } return cnt; } topcoder SRM 618 DIV2 WritingWords,布布扣,bubuko.com

topcoder SRM 618 DIV2 MovingRooksDiv2

一开始Y1,Y2两个参数看不懂,再看一遍题目后才知道,vector<int>索引代表是行数,值代表的是列 此题数据量不大,直接深度搜索即可 注意这里深度搜索的访问标识不是以前的索引和元素,而是一个交换元素后的整个状态vector<int>,这样可以避免重复元素的搜索 set<vector<int> > visit; bool flag; void dfs(vector<int>& src, vector<int>& d

topcoder SRM 618 DIV2 LongWordsDiv2

此题给出的条件是: (1)word的每个字母都是大写字母(此条件可以忽略,题目给的输入都是大写字母) (2) 相等字符不能连续,即不能出现AABC的连续相同的情况 (3)word中不存在字母组成xyxy的形式,即不存在第一个字符和第3个字符相等同时第2个字符和第4个字符相等的情况 对于第(2)种情况,只需要考虑word[i]!=word[i-1]即可 对于第(3)种情况,用一个4重循环遍历每种可能的情况,然后第一个字符和第3个字符相等同时第2个字符和第4个字符相等,则输出“DisLikes”即可

TOPCODER SRM 686 div2 1000

// TOPCODER SRM 686 div2 1000 Problem Statement 给出一个至多长 100 的字符串,仅包含 ( 和 ),问其中有多少个不重复的,合法的括号子序列. 子序列可以不连续:合法即括号序列的合法:答案模 1,000,000,007. Examples "(())(" Returns: 2 Correct non-empty bracket subsequences are "()" and "(())". &

SRM 628 DIV2

250  想想就发现规律了. 500  暴力,括号匹配. 1000 给一个f数组,如果i存在,那么f[i]也得存在,问这样的集合有多少种. 先拓扑一下,dp[i] = mul(dp[son]+1)最后环里面的元素的乘积是结果. #include <iostream> #include <cstdio> #include <string> #include <algorithm> #include <stdlib.h> #include <v

topcoder srm 628 div2 250 500

做了一道题,对了,但是还是掉分了. 第二道题也做了,但是没有交上,不知道对错. 后来交上以后发现少判断了一个条件,改过之后就对了. 第一道题爆搜的,有点麻烦了,其实几行代码就行. 250贴代码: 1 #include <iostream> 2 #include <cstring> 3 #include <queue> 4 #include <cmath> 5 #include <cstdio> 6 #include <algorithm&g