• 【数学题】【Codeforces 164 Div2 E】【Playlist】


    【题目来源】http://www.codeforces.com/contest/268/problem/E

    【个人体会】总算知道这个题目的正解了。。。借助了2位大神的力量(其实事实是我根本没出脑力,只打了个程序)。。。

    【题目大意】有N首歌,每首歌喜欢的概率为P[I],每首歌的时间为L[I]。一共有N!种排列方式来录制这些歌曲,对于每种排列方式,这个人开始听,遇到喜欢的歌曲,会接着听下一首歌曲;遇到不喜欢的歌曲,会把在这首歌之前的所有喜欢的歌听一遍,之后再回头来接着听下一首歌曲。最后求出数学期望总时间最长的那个时间。

    【题目分析】1.对于I和J这2个位置,倘若这个人喜欢I,并且不喜欢J,那么I这首歌将会被再听一遍。发生这件事情的概率是P[I]*(1-P[J]),这件事情将会产生L[I]*P[I]*(1-P[J])的数学期望时间加成。

          2.假设现在只有2个人I和J,那么若L[I]*P[I]*(1-P[J]) > L[J]*P[J]*(1-P[I]),则说明I带来的数学期望时间加成会更多,那么I应当放在开头,J放在末尾。

          3.对于人多的情况先考虑简单一点的,2个人相邻I和I+1,现在考虑是否要交换它们2个,

             如果I在前面那么,数学期望的加成是:

             (1-P[I])*(P[1]*L[1]+P[2]*L[2]+...+P[I-1]*L[I-1]) +  (1-P[I+1])*(P[1]*L[1]+P[2]*L[2]+...+P[I-1]*L[I-1]+P[I]*L[I]);

                        如果I+1在前面,那么,数学期望的加成是

                        (1-p[I+1])*(P[1]*L[1]+P[2]*L[2]+...+P[I-1]*L[I-1]) + (1-P[I])*(P[1]*L[1]+P[2]*L[2]+...+P[I-1]*L[I-1]+P[I+1]*L[I+1]);

           两式相减,最终取决于(1-P[I+1])*P[I]*L[I]和(1-P[I])*P[I+1]*L[I+1]的大小关系。

          4.(1-P[I+1])*P[I]*L[I]和(1-P[I])*P[I+1]*L[I+1]  等价于  P[I]*L[I]/(1-P[I])和P[I+1]*L[I+1]/(1-P[I+1])

          5.将P[I]*L[I]/(1-P[I])视为A[i],即I的比较函数。对于一个序列来说,倘若它有最大的数学期望值,那么A[i]必然是严格递减的,否则经过两两交换的方法,必然能使得总期望值最大。

    【代码如下】

     1 #include <iostream>
     2 #include <iomanip>
     3 #include <cstdio>
     4 #include <cstring>
     5 #include <cstdlib>
     6 #include <cmath>
     7 #include <vector>
     8 #include <deque>
     9 #include <stack>
    10 #include <queue>
    11 #include <algorithm>
    12 
    13 //#define FILE_IO
    14 #define DEBUG
    15 
    16 const int Maxn = 50005;
    17 int N, A[Maxn];
    18 double L[Maxn], P[Maxn], Sum[Maxn], Ans;
    19 
    20 using namespace std;
    21 
    22 bool Cmp(const int &i, const int &j)
    23 {
    24     return (P[i] * L[i] * (1 - P[j] / 100)) > (P[j] * L[j] * (1 - P[i] / 100));
    25 }
    26 
    27 int main()
    28 {
    29     #ifdef FILE_IO
    30     freopen("test.in", "r", stdin);
    31     #endif // FILE_IO
    32     scanf("%d", &N);
    33     for (int i = 1; i <= N; ++i)
    34     {
    35         scanf("%lf%lf", &L[i], &P[i]);
    36         A[i] = i;
    37     }
    38     sort(A + 1, A + 1 + N, Cmp);
    39     for (int i = 1; i <= N; ++i)
    40         Sum[i] = Sum[i - 1] + L[A[i]] * P[A[i]];
    41     for (int i = 1; i <= N; ++i)
    42         Ans += L[i] * 10000;
    43     for (int i = 2; i <= N; ++i)
    44         Ans += (100 - P[A[i]]) * Sum[i - 1];
    45     cout << setprecision(12) << setiosflags(ios :: fixed) << Ans / 10000 << endl;
    46     return 0;
    47 }
  • 相关阅读:
    java基础问题1
    基本数据类型,string类型的瞎扯,final喜欢干的事儿。final string
    关于区块链不懂的东西
    需求更新表属性
    用户体验——响应时间
    后台运行任务nohup xxxxxx &
    jenkins打包maven工程发现有些包下载不下来
    jenkins复选框插件Extended Choice Parameter plugin
    jmeter上传文件tips
    airflow 简介
  • 原文地址:https://www.cnblogs.com/GXZC/p/2908129.html
Copyright © 2020-2023  润新知