2022牛客多校第二场部分题解

题目简述:

一个n的排列p,求最小的max(lis(p),lds(p))

思路:

最大值应该为sqrt(n)上去整,然后构造即可如:4 3 2 1 8 7 6 5 11 10 9

代码:

#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
#define SZ(v) (int) v.size()



void solve(int Case) {
    int n;
    cin >> n;
    int t = ceil(sqrt(n));
    int k = n / t;

    for (int i = 1; i <= k; i++) {
        int idx = i * t;
        for (int j = idx; j > idx - t; j--) cout << j << ' ';
    }
    if (n % t) {
        int x = n % t;
        int s = n;
        for (; x--;) cout << s-- << ' ';
    }
    cout << nline;
}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);


    for (cin >> _, Case = 1; Case <= _; Case++)
        solve(Case);

    return 0;
}

题目简述:

给了一个长度为m的字符串S,问有多少长度为n的括号序列,并且存在一个子序列是S

思路:

数据范围很明显是n3的dp,首先容易想到的是前i个中匹配到S的前j的方案数,
因为转移要合法,考虑到他是括号序列,括号序列在任意时刻都满足前缀的左括号数量大于等于右括号数量;
那么状态表示就是f[i][j][k]表示当前选择到前i个,匹配到s的前j个,并且选择了k个左括号,
状态转移就是要么左括号要么右括号,注意j和k枚举的范围。

if (j == 0) {
    f[i][j][k] = f[i - 1][j][k - 1] + f[i - 1][j][k];
} else if (s[j] == '(') {
    f[i][j][k] = f[i - 1][j - 1][k - 1] + f[i - 1][j][k] ;
} else {
    f[i][j][k] = f[i - 1][j - 1][k] + f[i - 1][j][k - 1] ;
}

代码:

#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
#define SZ(v) (int) v.size()

const int N = 250, mod = 1e9 + 7;
int f[N][N][N];
char s[N];
void solve(int Case) {
    int n, m;
    cin >> m >> n;
    cin >> (s + 1);
    for (int i = 0; i <= n; i++) {
        for (int j = 0; j <= m; j++) {
            for (int k = 0; k <= n; k++) {
                f[i][j][k] = 0;
            }
        }
    }
    f[0][0][0] = 1;
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j <= min(i, m); j++) {
            for (int k = ((i + 1 ) / 2); k <= i; k++) {
                if (j == 0) {
                    f[i][j][k] = f[i - 1][j][k - 1] + f[i - 1][j][k];
                } else if (s[j] == '(') {
                    f[i][j][k] = f[i - 1][j - 1][k - 1] + f[i - 1][j][k] ;
                } else {
                    f[i][j][k] = f[i - 1][j - 1][k] + f[i - 1][j][k - 1] ;
                }
                f[i][j][k] %= mod;
            }
        }
    }
    cout << f[n][m][n / 2] << nline;

}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);


    for (cin >> _, Case = 1; Case <= _; Case++)
        solve(Case);

    return 0;
}

题目简述:

有n个物品,m组关系,比如b,d物品之间,a个b可以转换成c个d,但是有可能会出现无限转换,现在要求一个w使得ab=cw*d,并且不能出现无限循环,求最大的w

思路:

ab=cwd,假设起初每个物品都有一个,建边b->d=a/c/w,表示一个d可以变成可以由a/c/w个b变过来,然后就很明显的连乘,看是否形成环,但是由于好多小于1的小数,
连乘容易丢失精度,可以选择log,log(a
b)就变成log(a)+log(b)

代码:

#include <bits/stdc++.h>
#define int long long
int _ = 0, Case = 1;
using namespace std;
#define all(v) begin(v),end(v)
#define nline '\n'
#define SZ(v) (int) v.size()


const int N = 2020;
int w[N];
using PII = pair<int, double>;
vector<PII> h[N];
int n, m;
bool vis[N];
double d[N];
int cnt[N];
bool check(double x) {
    x = log(x);
    queue<int>q;
    for (int i = 1; i <= n; i++) vis[i] = 1, d[i] = 0, cnt[i] = 0, q.push(i);
    while (q.size()) {
        auto t = q.front();
        q.pop();
        vis[t] = 0;
        for (auto [i, w] : h[t]) {
            if (d[i] > d[t] +w -x) {
                d[i] = d[t] + w - x;
                cnt[i] = cnt[t] + 1;
                if (cnt[i] >= n) return false;
                if (!vis[i]) {
                    vis[i] = 1;
                    q.push(i);
                }
            }
        }
    }
    return true;
}
void solve(int Case) {
    cin >> n >> m;
    for (int i = 1; i <= m; i++) {
        double a, c;
        int b, d;
        cin >> a >> b >> c >> d;
        h[b].push_back({d, log(a/ c)});
    }
    double l = 0, r = 5;
    for (int i = 0; i < 60; i++) {
        double mid = (l + r) / 2;
        if (check(mid)) l = mid;
        else r = mid;
    }
    cout << l << nline;
}

signed main() {
    ios::sync_with_stdio(false); cin.tie(nullptr);


//   for (cin>>_, Case = 1; Case <= _; Case++)
    solve(Case);

    return 0;
}
posted @ 2022-07-24 14:12  指引盗寇入太行  阅读(42)  评论(0编辑  收藏  举报