牛客20220723第二场

Link with Monotonic Subsequence

题目描述:
构造长度为 n 的排列 p,使得 max {lis(p), lds(p)} 最小
lis(p): p 的最长上升子序列的长度
lds(p): p 的最长下降子序列的长度

解:
max {lis(p), lds(p)} 的下界是多少?
如果 n = k,构造(n − k + 1 n − k + 2 ... n)...(k + 1 k + 2 ... 2k)(1 2 ... k)
证明: lds(p) = 最小上升子序列分划数 (Dilworth 定理)
⇒ lis(p) lds(p) ≥ n ⇒ max {lds(p), lis(p)} ≥图片说明

Link with Arithmetic Progression

题目描述:
给定一串整数a1、a2、a3、a4、an,将它调成等差数列b1、b2、b3、b4、bn
使得图片说明 最小

解:
这题本质上是线性回归的题目,有两种做法
1、直接套线性回归公式算出拟合直线
2、先算出x,y的平均值,根据线性回归的性质,可以知道这个点必在直线上,接着就可以利用三分法枚举斜率,同样可以计算出结果

方法1:直接套公式

#include<iostream>
#include <cstdio>
#include <cctype>
#include <iomanip>
#include<bits/stdc++.h>

using namespace std;
typedef long long ll;


namespace GTI {
    char gc(void) {
        const int S = 1 << 16;
        static char buf[S], *s = buf, *t = buf;
        if (s == t) t = buf + fread(s = buf, 1, S, stdin);
        if (s == t) return EOF;
        return *s++;
    }

    int gti(void) {
        int a = 0, b = 1, c = gc();
        for (; !isdigit(c); c = gc()) b ^= (c == '-');
        for (; isdigit(c); c = gc()) a = a * 10 + c - '0';
        return b ? a : -a;
    }
}
using GTI::gti;


ll arr[100005];

void solve() {
    ll n = gti();
    long double xy = 0, xx = 0, x_p = 0, y_p = 0;
    for (ll i = 1; i <= n; i++) {
        arr[i] = gti();
        xy += i * arr[i];
        xx += i * i;
        x_p += i;
        y_p += arr[i];
    }
    x_p = x_p / n;
    y_p = y_p / n;
    long double b = (xy - n * x_p * y_p) / (xx - n * x_p * x_p);
    long double a = y_p - b * x_p;
    long double res = 0;
    for (ll i = 1; i <= n; i++) {
        res += (b * i + a - arr[i]) * (b * i + a - arr[i]);
    }
    cout << fixed << setprecision(15) << res << endl;
}


int main() {
    int t = gti();
    while (t--) {
        solve();
    }
}

方法二:三分枚举斜率

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

ll y[100005];
ll n;
ld y_p, x_p;


#include <cstdio>
#include <cctype>

namespace GTI {
    char gc(void) {
        const int S = 1 << 16;
        static char buf[S], *s = buf, *t = buf;
        if (s == t) t = buf + fread(s = buf, 1, S, stdin);
        if (s == t) return EOF;
        return *s++;
    }

    int gti(void) {
        int a = 0, b = 1, c = gc();
        for (; !isdigit(c); c = gc()) b ^= (c == '-');
        for (; isdigit(c); c = gc()) a = a * 10 + c - '0';
        return b ? a : -a;
    }
}
using GTI::gti;

ld dis(ld k) {
    ld res = 0;
    for (ll i = 1; i <= n; i++) {
        res += pow((k * (i - x_p) + y_p - y[i]), 2);
    }
    return res;
}

void solve() {
    n = gti();
    ll yy = 0;
    for (ll i = 1; i <= n; i++) {
        y[i] = gti();
        yy += y[i];
    }
    y_p = (ld) yy / n;
    x_p = (ld) (1 + n) / 2;
    ld r = 1e9, l = -1e9, k1, k2, k, res;
    while (r - l > 1e-9) {
        k = (r - l) / 3;
        k1 = l + k;
        k2 = l + k + k;
        ld resk1 = dis(k1);
        ld resk2 = dis(k2);
        res = resk1 < resk2 ? resk1 : resk2;
        res=min(res,dis((k1+k2)/2));
        if (resk1 < resk2) {
            r = k2;
        } else {
            l = k1;
        }
    }
    cout << fixed << setprecision(15) << res << endl;
}

int main() {
    int t = gti();
    while (t--) {
        solve();
    }
}

Link with Game Glitch

题目描述:
有n个物品,给出m种合成方式,每种合成方式都是用a个b物品能合成c个d物品,所以可能有某种方式能够得到无限大的某种物品,为了避免这个问题,现在添加一个参数w,只能用a个b物品合成w*c个d物品,求出满足题意的最大的w

解:
建图,n个顶点,m条边,每条边的权值就是c/a,二分枚举w,每条边的权值就变成了w*c/a,如果存在一个边权乘积大于1的环,就可以无限得到物品,对每条边取-log,就变成了如果边权相加存在负环,那么就可以无限得到物品,这样就可以求出答案。

#include<iostream>
#include<vector>
#include<queue>
#include<cmath>
#include <iomanip>

using namespace std;

typedef long long ll;

struct edge {
    int to;
    double weight;
};

vector<edge> v[1005];
int times[1005];
double dis[1005];
bool contain[1005];
bool view[1005];
int n, m;
double w;

bool isloop() {
    queue<int> q;
    for (int i = 1; i <= n; i++) {
        dis[i] = 1e100;
        times[i] = 0;
        contain[i] = false;
        view[i] = false;
    }
    int cur;
    for (int i = 1; i <= n; i++) {
        if (view[i]) {
            continue;
        } else {
            q.push(i);
            dis[i] = 0;
            times[i] = 1;
            contain[i] = true;
            while (!q.empty()) {
                cur = q.front();
                q.pop();
                view[i] = true;
                contain[cur] = false;
                for (edge e: v[cur]) {
                    int to = e.to;
                    double wei = -log(e.weight * w);
                    if (dis[to] > dis[cur] + wei) {
                        dis[to] = dis[cur] + wei;
                        if (!contain[to]) {
                            times[to]++;
                            if (times[to] >= n) {
                                return true;
                            }
                            q.push(to);
                            contain[to] = true;
                        }
                    }
                }
            }
        }

    }
    return false;
}

int main() {
    cin >> n >> m;
    int a, b, c, d;
    //建图
    for (int i = 0; i < m; i++) {
        cin >> a >> b >> c >> d;
        edge e = {d, c * 1.0 / a};
        v[b].push_back(e);
    }
    double l = 0, r = 1, res = 0;
    while (r - l > 1e-9) {
        w = (l + r) / 2;
        if (!isloop()) {
            l = w;
            res = w;
        } else {
            r = w;
        }
    }
    cout << fixed << setprecision(10) << res << endl;
}

Link with Bracket Sequence I

题目描述:
已知括号序列 a 是一个长度为 m 的合法括号序列 b 的子序列,求可能的序列 b 的数量。

解:
dp[i][j][k]表示a的前i个,与b的最大公共子序列为j,此时左括号比右括号多k个

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

const ll mod = 1e9 + 7;
int n, m;
ll f[205][205][205];
char chars[205];

void add(ll &a, ll b) {
    a = (a + b) % mod;
}

void solve() {
    scanf("%d%d\n%s", &n, &m, chars + 1);
    //归零
    for (int i = 0; i <= m; i++) {
        for (int j = 0; j <= n; j++) {
            for (int k = 0; k <= m; k++) {
                f[i][j][k] = 0;
            }
        }
    }
    //b的前0个中,与a的最长公共子序列为0,左括号比右括号多0的情况为1,即空串为1.
    f[0][0][0] = 1;
    for (int i = 0; i <= m; i++) {//表示b的前i个字符
        for (int j = 0; j <= n; j++) {//表示b与a的最长公共子序列
            for (int k = 0; k <= i; k++) {//表示左括号比右括号多的个数
                if (k >= 1) {//如果左括号比右括号多,那么a的下一个位置放右括号
                    if (j + 1 <= n && chars[j + 1] == ')') {//如果在下一个放右括号,并且b在这个位置的下一个也是右括号,那么最长公共子序列就会加一
                        add(f[i + 1][j + 1][k - 1], f[i][j][k]);
                    } else {
                        add(f[i + 1][j][k - 1], f[i][j][k]);
                    }
                }
                //左右括号一样多,我们放左括号
                if (j + 1 <= n && chars[j + 1] == '(') {
                    add(f[i + 1][j + 1][k + 1], f[i][j][k]);
                } else {
                    add(f[i + 1][j][k + 1], f[i][j][k]);
                }
            }
        }
    }

    cout << f[m][n][0] << endl;
}


int main() {
    int t;
    cin >> t;
    while (t--) {
        solve();
    }
}
#ACM##算法##来新手村#
全部评论
好巧呀,我也遇到这个题了,但当时没做出来
点赞 回复 分享
发布于 2022-08-10 18:28

相关推荐

牛客383479252号:9,2学生暑期实习失利开始投小厂,给这群人整自信了
点赞 评论 收藏
分享
咦哟,从去年八月份开始长跑,两处实习转正都失败了,风雨飘摇,终于拿到offer了更新一下面试记录:秋招:多部门反复面试然后挂掉然后复活,具体问了啥已经忘了,只是被反复煎炸,直至焦香😋春招:base北京抖音hr打来电话说再次复活,准备面试,gogogo北京抖音一面:六道笔试题:1.promise顺序2.定义域问题3.flat展开4.并发请求5.岛屿数量算法(力扣)深度,广度都写6.忘记了,好像也是算法,难度中等其他问题多是框架底层设计,实习项目重难点~~~秒过😇北京抖音二面:三道笔试题:(为什么只有三道是因为第三道没做出来,卡住了)1.中等难度算法(忘记啥题了,应该是个数组的)2.认识js的继承本质(手写继承模式,深入js的面相对象开发)3.手写vue的响应式(卡在了watch,导致挂掉)---后知后觉是我的注册副作用函数写得有问题,有点紧张了其他题目多是项目拷打,项目亮点,对实习项目的贡献~~~第二天,挂,but立马复活转战深圳客服当天约面深圳客服一面:六道笔试题,由于面过太多次字节,面试官叫我直接写,不用讲,快些写完😋,具体都是些继承,深拷贝(注意对数组对象分开处理,深层次对象,循环引用),加中等难度算法题~~~秒过深圳客服二面:口诉八股大战:大概囊括网络,浏览器渲染原理,动画优化,时间循环,任务队列等等(你能想到的简单八股通通拉出来鞭尸😋)算法题:笔试题6道:1:找出数组内重复的数,arr[0]-arr[n]内的数大小为[1-n],例如[1,2,2,3,3]返回[2,3],要求o(n),且不使用任何额外空间(做到了o(n),空间方面欠佳,给面试官说进入下一题,做不来了)2:原滋原味的继承(所以继承真滴很重要)3:力扣股票购买时机难度中等其他滴也忘记了,因为拿到offer后鼠鼠一下子就落地了,脑子自动过滤掉可能会攻击鼠鼠的记忆😷~~~秒过深圳客服三面:项目大战参与战斗的人员有:成员1:表单封装及其底层原理,使用成本的优化,声明式表单成员2:公司内部库生命周期管理成员3:第三方库和内部库冲突如何源码断点调试并打补丁解决成员4:埋点的艺术成员5:线上项目捷报频传如何查出内鬼成员6:大文件分片的风流趣事成员7:设计模式对对碰成员8:我构建hooks应对经理的新增的小需求的故事可能项目回答的比较流利,笔试题3道,都很简单,相信大家应该都可以手拿把掐😇~~~过过过无hr面后续煎熬等待几天直接hr打电话发offer了,希望大家也可以拿到自己心仪的offer
法力无边年:牛哇,你真是准备得充分,我对你没有嫉妒,都是实打实付出
查看19道真题和解析
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务