[cf1067D]Computer Game

令$Max=max_{i=1}^{n}p_{i}b_{i}$,显然这是每一个时刻的最大期望收益,因此当第一次胜利后,一定升级$Max$对应的这个游戏并一直玩,使得之后每一个时刻都取到这个最大期望收益

定义$f_{t}$表示可以玩$t$次的最大期望收益(初始状态下,即没有升级过任何游戏),转移考虑枚举第$t$个时刻玩的游戏,即$f_{t}=max_{i=1}^{n} p_{i}(a_{i}+(t-1)Max)+(1-p_{i})f_{t-1}$

简单变形,即$f_{t}=f_{t-1}+max_{i=1}^{n} p_{i}((t-1)Max-f_{t-1})+p_{i}a_{i}$

关于这个问题,即每一个游戏$i$对应于直线$l_{i}:y=p_{i}x+p_{i}a_{i}$,求$x=(t-1)Max-f_{t-1}$时的最大值

我们希望$x$有单调性,即$tMax-f_{t}ge (t-1)Max-f_{t-1}$,也即$Maxge f_{t}-f_{t-1}$

从定义的角度来看,考虑让$f_{t-1}$与$f_{t}$的前$t-1$次相同,显然最后一次的收益小于等于$Max$,即成立

由此,对这$n$条直线维护一个下凸壳,假设凸壳上的直线依次为$l_{b_{0}},l_{b_{1}},....,l_{b_{k}}$,其中直线$l_{b_{i}}$和$l_{b_{i+1}}$交点$x$坐标为$x_{i}$,问题即求$pos_{i}=max_{tMax-f_{t}le x_{i}}t+1$(特别的,$pos_{-1}=0$且$pos_{k}=infty$)

求出$pos_{i}$后,对于$tin (pos_{i-1},pos_{i}]$,都有$f_{t}=(1-p_{b_{i}})f_{t-1}+(t-1)p_{b_{i}}Max+p_{b_{i}}a_{b_{i}}$,显然可以用矩阵乘法维护,即
$$
left(egin{matrix}f_{t-1} &t-1&1\end{matrix} ight)left(egin{matrix}1-p_{b_{i}} &0&0\p_{b_{i}}Max&1&0\p_{b_{i}}a_{b_{i}}&1&1\end{matrix} ight)=left(egin{matrix}f_{t} &t&1\end{matrix} ight)
$$
矩阵快速幂即可,复杂度为$o(nlog n)$

从前往后依次求$pos_{i}$,即已经求出$pos_{i-1}$和$f_{pos_{i-1}}$,现在来求$pos_{i}$

构造序列$egin{cases}g_{t}=f_{t}&(t=pos_{i-1})\g_{t}=g_{t-1}+p_{b_{i}}((t-1)Max-g_{t-1})+p_{b_{i}}a_{b_{i}}&(t>pos_{i-1})end{cases}$

与$f$类似,也有$tMax-g_{t}ge (t-1)Max-g_{t-1}$,具体证明类似,这里就省略了

由此,通过二分+矩阵快速幂,即可$o(log^{2}n)$求出$ans=max_{tMax-g_{t}le x_{i}}t+1$

由于在$tin [pos_{i-1},pos_{i}]$中$g_{t}=f_{t}$且$g_{pos_{i}+1}le f_{pos_{i}+1}$,不难证明$pos_{i}=ans$,即求出$pos_{i}$

总复杂度为$o(nlog^{2}n)$,可以通过

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define N 100005
 4 #define ll long long
 5 int n,x,st[N];
 6 ll t,pos[N];
 7 double Max,ans,f[N];
 8 struct Data{
 9     int a;
10     double p;
11     bool operator < (const Data &k)const{
12         return (p<k.p)||(p==k.p)&&(a>k.a);
13     }
14 }a[N];
15 double get(int x,int y){
16     return (a[y].p*a[y].a-a[x].p*a[x].a)/(a[x].p-a[y].p);
17 }
18 struct matrix{
19     double a[3][3];
20     matrix(int p){
21         memset(a,0,sizeof(a));
22         if (p)a[0][0]=a[1][1]=a[2][2]=1;
23     }
24 };
25 matrix mul(matrix x,matrix y){
26     matrix z(0);
27     for(int i=0;i<3;i++)
28         for(int j=0;j<3;j++)
29             for(int k=0;k<3;k++)z.a[i][j]+=x.a[i][k]*y.a[k][j];
30     return z;
31 }
32 matrix qpow(matrix n,ll m){
33     matrix s=n,ans(1);
34     while (m){
35         if (m&1)ans=mul(ans,s);
36         s=mul(s,s);
37         m>>=1;
38     }
39     return ans;
40 }
41 double calc(int i,ll n,ll lst,double ans){
42     matrix A(1);
43     A.a[0][0]-=a[i].p;
44     A.a[1][0]=a[i].p*Max;
45     A.a[2][0]=a[i].p*a[i].a;
46     A.a[2][1]=1;
47     A=qpow(A,n-lst);
48     return A.a[0][0]*ans+A.a[1][0]*lst+A.a[2][0];
49 }
50 int main(){
51     scanf("%d%lld",&n,&t);
52     for(int i=1;i<=n;i++){
53         scanf("%d%d%lf",&a[i].a,&x,&a[i].p);
54         Max=max(Max,a[i].p*x);
55     }
56     sort(a+1,a+n+1);
57     for(int i=1;i<=n;i++){
58         if ((i>1)&&(a[i].p==a[i-1].p))continue;
59         while ((st[0]>1)&&(get(i,st[st[0]])<get(st[st[0]],st[st[0]-1])))st[0]--;
60         st[++st[0]]=i;
61     }
62     ll lst=0;
63     ans=0;
64     for(int i=1;i<st[0];i++){
65         double x=get(st[i],st[i+1]);
66         if (lst*Max-ans>x)continue;
67         ll l=lst,r=t-1;
68         while (l<r){
69             ll mid=(l+r+1>>1);
70             if (mid*Max-calc(st[i],mid,lst,ans)<=x)l=mid;
71             else r=mid-1;
72         }
73         l++;
74         ans=calc(st[i],l,lst,ans);
75         lst=l;
76         if (l==t){
77             printf("%.8f",ans);
78             return 0;
79         }
80     }
81     printf("%.8f",calc(st[st[0]],t,lst,ans));
82 }
View Code
原文地址:https://www.cnblogs.com/PYWBKTDA/p/14822014.html