首页 > 其他分享 >[题解]AT_abc342_f [ABC342F] Black Jack

[题解]AT_abc342_f [ABC342F] Black Jack

时间:2024-06-23 13:11:24浏览次数:3  
标签:res int 题解 sum read abc342 Black double dp

思路

发现自己与庄家的操作是完全独立的,所以考虑分别计算它们。

首先考虑自己的情况,定义 \(dp_i\) 表示掷出骰子的和为 \(i\) 获胜的概率,并记 \(f(i)\) 表示 \(x = i\) 时就不掷的获胜概率。

对于每一步我们要么掷骰子(并且掷出的值等概率的在 \(1 \sim D\) 中),要么直接结束。两种情况结合容易得出状态转移方程:

\[dp_i = \max(\frac{\sum_{j = i + 1}^{i + D}{dp_j}}{D},f(i)) \]

于是现在的问题就转化为了如何计算 \(f(i)\)。根据题目,获胜有两种情况,\(y > n\) 或者 \(x > y\)。现在 \(x,n\) 都已知,关键点就在于 \(y\)。

定义 \(g_i\) 表示庄家最终掷出结果为 \(i\) 的概率。那么 \(y > n\) 的情况就是 \(1 - \sum_{i = 1}^{n}{g_i}\);\(x > y\) 的情况就是 \(\sum_{i = 1}^{x - 1}{g_i}\)。显然可以前缀和优化一下。

考虑如何求 \(g\)。发现 \(g_i\) 会等概率地贡献给 \(g_{(i + 1) \sim (i + D)}\),因此每次:

\[\forall j \in [i + 1,i + D],g_j \leftarrow g_j + \frac{g_i}{D} \]

但是这样转移是 \(\Theta(LD)\) 的,同时注意到转移本质上是一个区间修改,单点查询,可以使用树状数组维护。

同时,根据题目,当 \(y < L\) 时是还会继续掷骰子的,因此需要将 \(g_{1 \sim (L - 1)}\) 在转移完成后清零。

Code

#include <bits/stdc++.h>
#define re register
#define double long double

using namespace std;

const int N = 4e5 + 10;
int n,l,d;
double g[N],dp[N];

inline int read(){
    int r = 0,w = 1;
    char c = getchar();
    while (c < '0' || c > '9'){
        if (c == '-') w = -1;
        c = getchar();
    }
    while (c >= '0' && c <= '9'){
        r = (r << 3) + (r << 1) + (c ^ 48);
        c = getchar();
    }
    return r * w;
}

struct BIT{
    #define lowbit(x) (x & -x)

    double tr[N];

    inline void modify(int x,double k){
        for (re int i = x;i <= 4e5;i += lowbit(i)) tr[i] += k;
    }

    inline double query(int x){
        double res = 0.0;
        for (re int i = x;i;i -= lowbit(i)) res += tr[i];
        return res;
    }

    #undef lowbit
}T;

inline double f(int x){
    if (x > n) return 0.0;
    double res = 1.0 - g[n];
    if (x) res += g[x - 1];
    return res;
}

int main(){
    g[0] = 1.0;
    n = read(),l = read(),d = read();
    for (re int i = 0;i <= 4e5;i++){
        if (i) g[i] = T.query(i);
        if (i < l){
            T.modify(i + 1,g[i] / d),T.modify(i + d + 1,-g[i] / d);
            g[i] = 0.0;
        }
    }
    for (re int i = 1;i <= 4e5;i++) g[i] += g[i - 1];
    double sum = 0.0;
    for (re int i = 4e5;~i;i--){
        if (i > n) dp[i] = 0.0;
        else dp[i] = max(sum / d,f(i));
        sum += dp[i];
        if (i + d <= 4e5) sum -= dp[i + d];
    }
    printf("%.15Lf",dp[0]);
    return 0;
}

标签:res,int,题解,sum,read,abc342,Black,double,dp
From: https://www.cnblogs.com/WaterSun/p/18263287

相关文章

  • [题解]CF855E Salazar Slytherin's Locket
    思路毒瘤数位DP题。首先,你可以用一个vector储存每一个数字出现的次数,然后用map记忆化。然后可以得到如下TLE#8的代码。因为map自带一只\(\log\)所以,考虑将map优化掉。但是,现在每一种数字可能会出现很多次,所以要用vector维护出现次数,但这样必定需要用map一......
  • [题解]CF666B World Tour
    CSP-2022S2T1弱化版。思路首先因为边权均为\(1\),所以我们可以在\(\Theta(n^2)\)的复杂度用BFS求解出任意两点\(i,j\)的最短距离\(d_{i,j}\)(如果\(i\)不能到达\(j\),则令\(d_{i,j}=-1\))。有一个贪心的结论,就是使每一条\(A\toB,B\toC,C\toD\)的路径长度......
  • [题解]CF622F The Sum of the k-th Powers
    思路首先发现\(\sum_{i=1}^{n}i^k\)是一个\(k+1\)次多项式,那么我们需要求出\(k+2\)个点才能得到唯一的一个\(f(t)=\sum_{i=1}^{t}{i^k}\)。不难通过拉格朗日插值法,将\(x=1\sim(k+2)\)的情况一一带入:\[f(n)=\sum_{i=1}^{k+2}{((\sum_{j=1}^{i}......
  • [题解]CF622D Optimal Number Permutation
    思路首先考虑答案下界,因为\((n-i)\)和\(|d_i+i-n|\)均大于等于\(0\),所以它们相乘一定大于等于\(0\)。于是考虑能不能构造出结果为\(0\)。显然当\(i=n\)时,无论\(d_i\)的值是什么,式子的结果为\(0\)。因此只需要考虑\(i\in[1,n)\)的情况。因为要使结果为......
  • [题解]CF609F Frogs and mosquitoes
    思路发现\(x\)对题目的限制较大,因此考虑先将\(x\)排序并离散化后再来考虑。不难用线段树维护\(\max_{i=l}^{r}\{x_i+len_i\}\),这样我们就可以利用类似线段树上二分的技巧得出是哪一只青蛙吃掉的蚊子。但是有可能有一只蚊子无法吃掉,我们先把它丢进一个集合里面。每有......
  • [题解]CF988D Points and Powers of Two
    思路首先发现选出的数最多\(3\)个,考虑反证法。假设选出了四个数\(a,b,c,d\),并令:\[|a-b|=2^{x_1},|b-c|=2^{x_2},|c-d|=2^{x_3}\]又因为,\(|a-c|,|b-d|\)也都是\(2\)的次幂,那么有\(x_1=x_2=x_3\)。于是\(|a-d|=3\times2^{x_0}\neq2^k\)。在......
  • P9999 [Ynoi2000] tmostnrq 题解
    巨大难写题。就这样一个毒瘤的题,还有人把时空缩小成二分之一放在模拟赛,太好笑了。思路首先将询问离线。我们在\(l_i\)处加入这个点,在\(r_i\)处查询这个点在哪里。那么我们就需要有一个数据结构支持让所有树上的节点一起动。考虑所有点往\(x\)处动。那么对于在\(1\si......
  • LeetCode:经典题之206、92题解及延伸
    系列目录88.合并两个有序数组52.螺旋数组567.字符串的排列643.子数组最大平均数150.逆波兰表达式61.旋转链表160.相交链表83.删除排序链表中的重复元素389.找不同目录系列目录206.反转链表92.反转链表II类和结构体访问修饰符206.反转链表......
  • UNIQUE VISION Programming Contest 2024 Summer (AtCoder Beginner Contest 359) 题
    点我看题A-CountTakahashi没啥好说的点击查看代码#include<bits/stdc++.h>#definerep(i,n)for(inti=0;i<n;++i)#definerepn(i,n)for(inti=1;i<=n;++i)#defineLLlonglong#definefifirst#definesesecond#definepbpush_back#definemprmake_pair......
  • abc359_G Sum of Tree Distance 题解
    题目链接:Atcoder或者洛谷先考虑暴力,显然是枚举整棵树的路径,这个枚举复杂度显示是\(O(n^2)\),还不考虑计算\(f(i,j)\),考虑使用点分治优化枚举复杂度:\(O(n\log{n})\)。接下来考虑如何计算每条路径的\(f(i,j)\),注意到\(f(i,j)\):当且仅当\(a[i]=a[j]\)时,答案加上\(dis(i,j......