2021牛客暑期多校训练营4

2021牛客暑期多校训练营4:B,C,E,F,I,J

B-Sample Game

题意

x x x 个数,随机到数 i i i 的概率是 p i p_i pi,现在进行以下步骤:

  1. 随机生成一个数
  2. 如果之前生成的所有数都不大于当前生成的这个数,则继续进行步骤1;
  3. 否则,进行分数结算并结束,若当前已经生成了 n u m num num​​​ 个数,则总分数为 n u m 2 num ^ 2 num2​ 。

问分数的期望。

思路

参考:【训练题43:概率dp】Sample Game | 2021牛客暑期多校训练营4

比赛的时候推出了一个大概的方程,但是没想出来怎么进行值的递推。赛后看官方题解是直接把式子推出来 O ( n ) O(n) O(n) 做的,我实在有点理解不了那个算式qwq,所以最后参考上面的链接用概率dp做了。

因为生成的序列一定是非降序的,只有最后一个数不是非降序,所以我们设 d p [ i ] dp[i] dp[i] 为数字生成到 i i i​ 时,最后数字总个数的期望值,设 d p 2 [ i ] dp2[i] dp2[i] 是数字生成到 i i i 时,最后数字总个数的平方的期望值,即分数的期望。

dp的转移方程推导

转移的思路为 概率*(下一个状态+贡献),首先我们看 d p dp dp​​ 数组的转移,若当前数字为 i i i​​ ,且下一个数字 j ≥ i j \geq i ji​​​ ,那就还可以接着选择,所以此时期望为 p j ∗ ( d p [ j ] + 1 ) p_j * (dp[j] + 1) pj(dp[j]+1)​​​;相反,若 j < i j < i ji​​ ,则没有能继续转移的状态,期望为 p j ∗ 1 p_j * 1 pj1​​。由此,我们得到 d p dp dp​​ 数组的转移方程式:
d p [ i ] = ∑ j = 1 i − 1 p [ j ] + ∑ j = i n p [ j ] ∗ ( d p [ j ] + 1 ) dp[i] = \sum_{j = 1}^{i - 1} p[j] + \sum_{j = i}^n p[j] * (dp[j] + 1) dp[i]=j=1i1p[j]+j=inp[j](dp[j]+1)

此时的左右式中均含有 d p [ i ] dp[i] dp[i]​​ ,因此我们将右侧的移至左侧,
d p [ i ] ∗ ( 1 − p [ i ] ) = ∑ j = 1 i − 1 p [ j ] + ∑ j = i + 1 n p [ j ] ∗ ( d p [ j ] + 1 ) + p i dp[i] * (1 - p[i]) = \sum_{j = 1}^{i - 1} p[j] + \sum_{j = i + 1}^n p[j] * (dp[j] + 1) + p_i dp[i](1p[i])=j=1i1p[j]+j=i+1np[j](dp[j]+1)+pi
得到最终的转移方程式
d p [ i ] = ∑ j = 1 i − 1 p [ j ] + ∑ j = i + 1 n p [ j ] ∗ ( d p [ j ] + 1 ) + p i 1 − p [ i ] dp[i] = \frac{\sum_{j = 1}^{i - 1} p[j] + \sum_{j = i + 1}^n p[j] * (dp[j] + 1) + p_i}{1 - p[i]} dp[i]=1p[i]j=1i1p[j]+j=i+1np[j](dp[j]+1)+pi

dp2的转移方程推导

之所以还需要计算 d p 2 dp2 dp2 ,是因为 E ( x 2 ) ! = E 2 ( x ) E(x^2) != E^2(x) E(x2)!=E2(x),所以我们不能简单的计算 d p dp dp 的平方。

若现在我们要得到 E ( ( x + 1 ) 2 ) E((x + 1)^2) E((x+1)2),则 E ( ( x + 1 ) 2 ) = E ( x 2 ) + 2 E ( x ) + 1 E((x + 1)^2) = E(x^2) + 2E(x) + 1 E((x+1)2)=E(x2)+2E(x)+1,即 E ( ( d p [ j ] + 1 ) 2 ) = d p 2 [ j ] + 2 ∗ d p [ j ] + 1 E((dp[j] + 1) ^ 2) = dp2[j] + 2 * dp[j] + 1 E((dp[j]+1)2)=dp2[j]+2dp[j]+1 ,所以对于 j ≥ i j \geq i ji 的情况,此时的期望为 p j ∗ E ( ( d p [ j ] + 1 ) 2 ) = p j ∗ ( d p 2 [ j ] + 2 ∗ d p [ j ] + 1 ) p_j * E((dp[j] + 1)^2) = p_j * (dp2[j] + 2 * dp[j] + 1) pjE((dp[j]+1)2)=pj(dp2[j]+2dp[j]+1) ;而 j < i j < i ji 的情况,由于个数部分为1,平方后不变,所以式子一样。由此,我们得到dp2的转移方程式:
d p 2 [ i ] = ∑ j = 1 i − 1 p [ j ] + ∑ j = i n p [ j ] ∗ ( d p 2 [ j ] + 2 d p [ j ] + 1 ) dp2[i] = \sum_{j = 1}^{i - 1} p[j] + \sum_{j = i}^n p[j] * (dp2[j] + 2dp[j] + 1) dp2[i]=j=1i1p[j]+j=inp[j](dp2[j]+2dp[j]+1)
再次将右项中的 d p 2 [ i ] dp2[i] dp2[i]​ 移动到左侧,
d p 2 [ i ] ∗ ( 1 − p [ i ] ) = ∑ j = 1 i − 1 p [ j ] + ∑ j = i + 1 n p [ j ] ∗ ( d p [ j ] + 1 ) + 2 ∗ d p [ i ] ∗ p i + p [ i ] dp2[i] * (1 - p[i]) = \sum_{j = 1}^{i - 1} p[j] + \sum_{j = i + 1}^n p[j] * (dp[j] + 1) + 2 * dp[i] * p_i + p[i] dp2[i](1p[i])=j=1i1p[j]+j=i+1np[j](dp[j]+1)+2dp[i]pi+p[i]
得到最终的转移方程式
d p 2 [ i ] = ∑ j = 1 i − 1 p [ j ] + ∑ j = i + 1 n p [ j ] ∗ ( d p [ j ] + 1 ) + 2 ∗ d p [ i ] ∗ p i + p [ i ] 1 − p [ i ] dp2[i] = \frac{\sum_{j = 1}^{i - 1} p[j] + \sum_{j = i + 1}^n p[j] * (dp[j] + 1) + 2 * dp[i] * p_i + p[i]}{1 - p[i]} dp2[i]=1p[i]j=1i1p[j]+j=i+1np[j](dp[j]+1)+2dp[i]pi+p[i]
代码实现上,先算一遍 d p dp dp ,再算一遍 d p 2 dp2 dp2 ,注意 d p [ i ] dp[i] dp[i] 的意思是已经取到 i i i 的情况下的长度期望,所以我们最终要求的其实是 d p 2 [ i + 1 ] dp2[i + 1] dp2[i+1],所以在加入答案时,加入 d p 2 [ i ] + 2 ∗ d p [ i ] + 1 dp2[i] + 2 * dp[i] + 1 dp2[i]+2dp[i]+1 而非 d p 2 [ i ] dp2[i] dp2[i]。​

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const double eps = 1e-10;

int n;
ll p[N];
ll dp[N], dp2[N];
const int mod = 998244353;

ll qpow(ll x, ll n)
{
    ll ans = 1LL;
    while(n)
    {
        if(n & 1)
            ans = (ans * x) % mod;
        x = x * x % mod;
        n >>= 1;
    }
    return ans;
}

ll inv(ll a)
{
    return qpow(a, mod - 2);
}

int main()
{
    cin >> n;
    ll sum = 0;
    for(int i = 1; i <= n; i++)
    {
        cin >> p[i];
        sum += p[i];
    }
    for(int i = 1; i <= n; i++)
    {
        p[i] = p[i] * inv(sum) % mod;
    }
    for(int i = n; i > 0; i--)
    {
        ll fenz = p[i];
        ll fenm = (1LL - p[i] + mod) % mod;
        for(int j = i + 1; j <= n; j++)
        {
            fenz = (fenz + (p[j] * (dp[j] + 1) % mod)) % mod;
        }
        for(int j = 1; j < i; j++)
        {
            fenz = (fenz + p[j]) % mod;
        }
        dp[i] = fenz * inv(fenm) % mod;
    }
    ll ans = 0;
    for(int i = n; i > 0; i--)
    {
        ll fenz = p[i] * ((2 * dp[i] + 1) % mod) % mod;
        ll fenm = (1LL - p[i] + mod) % mod;
        for(int j = i + 1; j <= n; j++)
        {
            fenz = (fenz + p[j] * (dp2[j] + 2LL * dp[j] % mod + 1) % mod) % mod;
        }
        for(int j = 1; j < i; j++)
        {
            fenz = (fenz + p[j]) % mod;
        }
        dp2[i] = fenz * inv(fenm) % mod;
        ans = (ans + (dp2[i] + dp[i] * 2LL % mod + 1) % mod * p[i] % mod) % mod;
    }
    cout << ans << endl;
    return 0;
}

C-LCS

题意

给定四个整数 a , b , c , n a, b, c, n a,b,c,n ,构造三个字符串,使得 L C S ( s 1 , s 2 ) = a , L C S ( s 2 , s 3 ) = b , L C S ( s 1 , s 3 ) = c LCS(s1, s2)=a, LCS(s2, s3)=b, LCS(s1, s3)=c LCS(s1,s2)=a,LCS(s2,s3)=b,LCS(s1,s3)=c 。​

思路

设有 a ≤ b ≤ c a \leq b \leq c abc,则我们按照以下方式构造:

在这里插入图片描述

所以只要 n ≥ b + c − a n \geq b + c - a nb+ca​ 就有解。

我是把abc先排序,最后再还原的,还原想不出什么好办法,直接枚举了。

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 3e5 + 5;

char str1[N], str2[N], str3[N];
char res1[N], res2[N], res3[N];

struct node
{
    char id;
    int num;
    bool operator < (const node& obj)
    {
        if(num == obj.num)
            return id < obj.id;
        return num < obj.num;
    }
};

node arr[N];

int main() {
    int a, b, c, n;
    cin >> a >> b >> c >> n;
    arr[0].num = a, arr[1].num = b, arr[2].num = c;
    arr[0].id = 'a', arr[1].id = 'b', arr[2].id = 'c';
    sort(arr, arr + 3);
    if(arr[1].num + arr[2].num - arr[0].num > n)
    {
        cout << "NO\n";
        return 0;
    }
    a = arr[0].num;
    b = arr[1].num;
    c = arr[2].num;
    for(int i = 0; i < a; i++)
    {
        str1[i] = 'a';
        str2[i] = 'a';
        str3[i] = 'a';
    }
    for(int i = a; i < b; i++)
    {
        str2[i] = 'b';
        str3[i] = 'b';
    }
    for(int i = 0; i < c - a; i++)
    {
        str1[i + a] = 'c';
        str3[i + b] = 'c';
    }
    for(int i = 0; i < n; i++)
    {
        if(!str1[i])
            str1[i] = 'd';
    }
    for(int i = 0; i < n; i++)
    {
        if(!str2[i])
            str2[i] = 'e';
    }
    for(int i = 0; i < n; i++)
    {
        if(!str3[i])
            str3[i] = 'f';
    }

    if(arr[0].id == 'a' && arr[1].id == 'b' && arr[2].id == 'c')
    {
        cout << str1 << '\n';
        cout << str2 << '\n';
        cout << str3 << '\n';
    }
    else if(arr[0].id == 'a' && arr[1].id == 'c' && arr[2].id == 'b')
    {
        cout << str2 << '\n';
        cout << str1 << '\n';
        cout << str3 << '\n';
    }
    else if(arr[0].id == 'b' && arr[1].id == 'a' && arr[2].id == 'c')
    {
        cout << str3 << '\n';
        cout << str2 << '\n';
        cout << str1 << '\n';
    }
    else if(arr[0].id == 'b' && arr[1].id == 'c' && arr[2].id == 'a')
    {
        cout << str3 << '\n';
        cout << str1 << '\n';
        cout << str2 << '\n';
    }
    else if(arr[0].id == 'c' && arr[1].id == 'a' && arr[2].id == 'b')
    {
        cout << str2 << '\n';
        cout << str3 << '\n';
        cout << str1 << '\n';
    }
    else if(arr[0].id == 'c' && arr[1].id == 'b' && arr[2].id == 'a')
    {
        cout << str1 << '\n';
        cout << str3 << '\n';
        cout << str2 << '\n';
    }
    return 0;
}

E-Tree Xor

题意

给定一颗树,每个点的权值 a i a_i ai [ l i , r i ] [l_i, r_i] [li,ri] 之间,已知每条边 u , v u, v u,v 的边权 w u , v = a u   x o r   a v w_{u, v} = a_u \ xor \ a_v wu,v=au xor av

思路

参考:2021牛客多校4_bok_choy_的博客 队友的博客

队友写的好好,我摸了()

具体实现见代码注释

代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef pair<int, int> P;
const int N = 1e5 + 10;

vector<P> seg;
int tr[N * 4]; //不能用结构体+build,点的范围太大了,会RE

//trL和trR是原本结构体中的tr[u].l, tr[u].r
void modify(int u, int trL, int trR, int l, int r, int dep, int Xor)
{
    if(dep < 0)
        return ;
    if(trL >= l && trR <= r) // 已经完全包含
    {
        int preL = trL & (((1 << 30) - 1) ^ ((1 << dep) - 1)); //原区间的相同前缀
        int preXor = Xor & (((1 << 30) - 1) ^ ((1 << dep) - 1));
        seg.push_back(P(preXor ^ preL, (preXor ^ preL) + (1 << dep) - 1));
        // preXor^preL: 新区间的相同前缀
        // (preXor ^ preL) + (1 << dep) - 1): 即后缀全1
        return ;
    }
    int mid = (trL + trR) >> 1;
    if(l <= mid)
        modify(u << 1, trL, mid, l, r, dep - 1, Xor);
    if(r > mid)
        modify(u << 1 | 1, mid + 1, trR, l, r, dep - 1, Xor);
}

int solve(int n)
{
    vector<P> vec;
    for(auto it : seg)
    {
        vec.push_back(P(it.first, -1)); //这里反过来,因为pair的优先级是先first后second,从小到大
        vec.push_back(P(it.second, 1));
    }
    int res = 0;
    sort(vec.begin(), vec.end());
    int len = vec.size();
    int cnt = 0;
    for(int i = 0; i < len; i++)
    {
        cnt -= vec[i].second;
        if(cnt == n) // 被覆盖n次,说明这个区间内的值都可以作为答案
            if(i + 1 < len)
                res += vec[i + 1].first - vec[i].first + 1;
    }
    return res;
}

int head[N], es[N * 2], nxt[N * 2], idx, cost[N * 2];
int a[N];

void addEdge(int u, int v, ll w)
{
    es[++idx] = v;
    nxt[idx] = head[u];
    cost[idx] = w;
    head[u] = idx;
}

// dfs求一组特解
void dfs(int u, int fa, ll w)
{
    a[u] = w;
    for(int i = head[u]; ~i; i = nxt[i])
    {
        int v = es[i];
        if(v == fa)
            continue;
        dfs(v, u, w ^ cost[i]);
    }
}

int l[N], r[N];

int main()
{
    int n;
    scanf("%d", &n);
    memset(head, -1, sizeof head);
    for(int i = 0; i < n; i++)
    {
        scanf("%d%d", l + i, r + i);
    }
    for(int i = 0, u, v; i < n - 1; i++)
    {
        ll w;
        scanf("%d%d%lld", &u, &v, &w);
        u--;
        v--;
        addEdge(u, v, w);
        addEdge(v, u, w);
    }
    dfs(0, -1, 0);
    for(int i = 0; i < n; i++)
    {
        modify(1, 0, (1 << 30) - 1, l[i], r[i], 30, a[i]);
    }
    printf("%d\n", solve(n));
    return 0;
}

F-Just a joke

题意

Alice和Bob玩游戏,Alice先手,给定无向图,可以选择一个边删除或者删除一个没有环的 c o n n e c t e d   c o m p o n e n t connected \ component connected component ​​​,即一个内部点互相都有边直接相连,与外部点没有边相连的子图。问谁会赢。

思路

比赛理解错题意了,以为三个点的完全图的情况应该算Alice赢(就是以为三个点的完全图是可以一次全部删除的),但是其实三个点的完全图是算一个环,所以不能删除,还是Bob赢,不过似乎测试数据里没有这个,所以我错误的理解还是过了。

比赛的做法是先通过 ( n + m ) (n + m) (n+m) 的奇偶性确定谁赢,再数有多少个能够改变输赢的 c o n n e c t e d   c o m p o n e n t connected \ component connected component​ ,若是奇数个是先手赢,偶数个是后手赢,没有的话维持原样。

但其实如果三元环不算的话,就没有能改变输赢的 c o n n e c t e d   c o m p o n e n t connected \ component connected component 了,直接就是判断奇偶。

代码

比赛代码

#include<bits/stdc++.h>
using namespace std;
const int N = 110;
const int M = 1e5 + 10;
int n, m;

struct edge{
    int u;
    int v;
    int nxt;
}es[M];
int head[N], tot;

void init(int _n) {
    tot = 0;
    for (int i = 0; i <= _n; i++)
        head[i] = -1;
}
void add_edge(int u, int v) {
    es[tot].u = u;
    es[tot].v = v;
    es[tot].nxt = head[u];
    head[u] = tot++;
}

int uu, ee;
int vis[N];
int vise[M];
void dfs(int u, int fa) {
    uu++;
    vis[u] = 1;
    for (int i = head[u]; i != -1; i = es[i].nxt) {
        int v = es[i].v;
        int id = i / 2;
        if (!vise[id]) ee++, vise[id] = 1;
        if (v == fa || vis[v]) continue;
        dfs(v, u);
    }
}

int main() {
    scanf("%d%d", &n, &m);
    init(n);
    for (int i = 0; i < m; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        add_edge(u, v);
        add_edge(v, u);
    }
    for (int i = 0; i <= n; i++) vis[i] = 0;
    for (int i = 0; i < tot; i++) vise[i] = 0;
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        if (vis[i]) continue;
        uu = 0, ee = 0;
        dfs(i, 0);
        // uu 当前连通块的点数  , ee是当前连通块的边数
        if (uu * (uu - 1) / 2 == ee) {
            if((uu + ee) % 2 == 0) {
                cnt++;
            }
        }
    }
    if(cnt % 2)
    {
        cout << "Alice" << endl;
    }
    else if(cnt)
    {
        cout << "Bob" << endl;
    }
    else
    {
        if((n + m) % 2)
        {
            cout << "Alice" << endl;
        }
        else
        {
            cout << "Bob" << endl;
        }
    }


    return 0;
}

正解

#include <bits/stdc++.h>
using namespace std;

int main()
{
    int n, m;
    cin >> n >> m;
    if((n + m) % 2) {
        cout << "Alice" << endl;
    }
    else {
        cout << "Bob" << endl;
    }
    return 0;
}

I-Inverse Pair

题意

给定一个排列,对排列中的部分数加1,使得得到的新序列的逆序对个数最少。输出最少的逆序对数量。

思路

因为是排列,所以加1最多只会和某一个数相等,不会增加未出现的逆序对;且加一也只能消除一对逆序对,即贡献为1。但是如果 ( 2 , 1 ) (2, 1) (2,1)​ 变成了 ( 2 , 2 ) (2, 2) (2,2)​​ 后,我们又为了消除逆序对 ( 3 , 2 ) (3, 2) (3,2)​​ 把2改成3,则会还原原来已经消除的逆序对。所以我们统计有多少个差为1的逆序对,再对于前面提到的这种需要避免的情况特判,就可以得到最终答案。

小教训:数组越界的情况要小心

(懒了,扔个队友代码)

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 5;
int tre[maxn];
int lowbit(int x) {
    return x & (-x);
}
int n;
void add(int p, int v) {
    while(p <= n) {
        tre[p] += v;
        p += lowbit(p);
    }
}
int qry(int p) {
    ll ans = 0;
    while(p > 0) {
        ans += tre[p];
        p -= lowbit(p);
    }
    return ans;
}

int main() {
    cin >> n;
    vector<int>res(n);
    vector<int>pos(n + 1, 0);
    for(int i = 0; i < n; i++) {
        cin >> res[i];
        pos[res[i]] = i;
    }
    ll ans = 0;
    for(int i = 0; i < n; i++) {
        ans += (ll)(i - qry(res[i]));
        add(res[i], 1);
    }
    vector<pair<int, int> > p;
    for(int i = 1; i < n; i++) {
        if(pos[i] > pos[i + 1]) {
            p.push_back(make_pair(i, i + 1));
        }
    }
    sort(p.begin(), p.end());
    vector<int>vis(n + 1, 0);
    for(int i = 0; i < p.size(); i++) {
        if(!vis[p[i].first] && !vis[p[i].second]) {
            ans--;
            vis[p[i].first] = 1;
            vis[p[i].second] = 1;
        }
    }
    cout << ans;
}

J-Average

题意

给定一个 n × m n \times m n×m 的矩阵,找到大小最少为 x × y x \times y x×y 的子矩阵,使得其内所有数平均值最大,输出最大平均值。

思路

这题要从该矩阵的生成函数来看。

This matrix is very special, It’s calculated by two sequences a 1... n , b 1... m , ∀ i ∈ [ 1 , n ] , ∀ j ∈ [ 1 , m ] , W i , j = a i + b j a_{1...n},b_{1...m}, \forall i\in [1,n],\forall j\in [1,m], W_{i,j}=a_{i}+b_{j} a1...n,b1...m,i[1,n],j[1,m],Wi,j=ai+bj

所以,对于一个 x × y x \times y x×y 左上顶点为 ( l , u ) (l, u) (l,u) 的矩阵,其所有数字之和为:
y ∗ ∑ i = l l + x a i + x ∗ ∑ i = u u + y b i y * \sum_{i = l}^{l + x} a_i + x * \sum_{i = u}^{u + y} b_i yi=ll+xai+xi=uu+ybi
因此,其平均数为:
∑ i = l l + x a i + x x + ∑ i = u u + y b i y \frac{\sum_{i = l}^{l + x} a_i + x}{x} + \frac{\sum_{i = u}^{u + y} b_i}{y} xi=ll+xai+x+yi=uu+ybi
由此,问题转化为求 a a a​​ 数组中长度至少为 x x x​​ 的子段的最大字段和与 b b b​​ 数组中长度至少为 y y y​​​ 的子段的最大字段和。

求最大子段和可以二分处理,设答案为S,把数组所有数全部减S,看是否存在一个平均值大于0的子段,若有则满足。

代码

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int N = 1e5 + 10;
const double eps = 1e-10;

int n, m;
double x, y;
double a[N], b[N];

int dcmp(double num)
{
    if(fabs(num) < eps)
        return 0;
    return num > 0 ? 1 : -1;
}

bool oka(double num)
{
    vector<double> sum(n + 1);
    sum[0] = 0;
    for(int i = 1; i <= n; i++)
    {
        sum[i] = a[i] - num + sum[i - 1];
    }
    double minn = INF;
    for(int i = x; i <= n; i++)
    {
        minn = min(minn, sum[i - x]);
        if(dcmp(sum[i] - minn) >= 0)
        {
            return true;
        }
    }
    return false;
}

bool okb(double num)
{
    vector<double> sum(m + 1);
    sum[0] = 0;
    for(int i = 1; i <= m; i++)
    {
        sum[i] = b[i] - num + sum[i - 1];
    }
    double minn = INF;
    for(int i = y; i <= m; i++)
    {
        minn = min(minn, sum[i - y]);
        if(dcmp(sum[i] - minn) >= 0)
        {
            return true;
        }
    }
    return false;
}


int main()
{
    cin >> n >> m >> x >> y;
    double maxa = 0, maxb = 0;
    double ans = 0;
    for(int i = 1; i <= n; i++)
    {
        cin >> a[i];
        maxa = max(maxa, a[i]);
    }
    for(int i = 1; i <= m; i++)
    {
        cin >> b[i];
        maxb = max(maxb, b[i]);
    }
    double l = 0, r = maxa;
    while(dcmp(r - l) > 0)
    {
        double mid = (l + r) / 2.0;
        if(oka(mid))
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    ans += l;
    l = 0, r = maxb;
    while(dcmp(r - l) > 0)
    {
        double mid = (l + r) / 2.0;
        if(okb(mid))
        {
            l = mid;
        }
        else
        {
            r = mid;
        }
    }
    ans += l;
    printf("%.12f\n", ans);
    return 0;
}
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值