“蔚来杯“2022牛客暑期多校训练营1 GADIJ

"蔚来杯"2022牛客暑期多校训练营1 GADIJ

G Lexicographical Maximum

/*判断n是否满足 若干个9最后一位为任意数字 如: 99997 99999 若满足则直接输出 n 否则输出 n 的位数减一个 9*/
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
int main(){
    string s;
    cin >> s;
    int flag = true;
    for(int i = 0; i < s.size() - 1 ; i ++){
        if(s[i] != '9'){
            flag = false;
            break;
        }
    }
    if(flag){
        cout<< s ;
    }
    else{
        for(int i = 0; i < s.size() - 1 ; i ++){
            cout << "9" ;
        }
    }
    return 0;
}

A Villages: Landlines

/*
给定n个电塔的信息(电塔的坐标, 电塔的作用半径)[可以视为一个区间], 电塔作用范围链接的费用为两个端点的距离,问使得所有电塔相连的最小费用。
*/
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define int long long 
using namespace std;
const int N = 2e5 + 10;
typedef pair<int,int> PII;
PII a[N];
int n, ans;
signed main(){
    scanf("%lld", &n);
    for(int i = 0; i < n ; i ++){
        int x, y;
        scanf("%lld%lld",&x, &y);
        a[i] = {x - y, x + y};
    }
    sort(a, a + n);
    int l = a[0].first;
    int r = a[0].second;
    for(int i = 1; i < n ; i ++){
        if(a[i].first <= r){
            l = min(l, a[i].first);
            r = max(r, a[i].second);
        }
        else{
            ans += (a[i].first - r);
            l = min(l, a[i].first);
            r = max(r, a[i].second);
        }
    }
    printf("%lld\n", ans);
}

D Mocha and Railgun

/*
延长线经过圆心时圆弧长度最大
*/
#include <bits/stdc++.h>
using namespace std;
const double eps = 1e-10;
double r, x, y, d, w, l, a1, a2, ans, h;

signed main()
{
    ios::sync_with_stdio(0);
    cout << fixed << setprecision(12);
    int t;
    cin >> t;
    while (t--)
    {

        cin >> r;
        cin >> x >> y >> d;
        w = sqrt(x * x + y * y);
        h, l, ans, a1, a2;
        if (d < w)
        {
            h = w + d;
            l = w - d;
            a1 = h / r;
            a2 = l / r;
            ans = (acos(a2) - acos(a1)) * r;
        }
        else
        {
            h = w + d;
            l = d - w;
            a1 = h / r;
            a2 = l / r;
            ans = (acos(-1) - (acos(a2) + acos(a1))) * r;
        }
        cout << ans << endl;
    }
}

I Chiitoitsu

/*
概率dp
一、目标状态,达到目标状态之后结束。
二、dp[状态],在当前状态下还需要几步达到目标状态, dp[目标状态] = 0。
三、影响答案的因素有:当前手中还有几个单牌, 卡池中抽出手中单牌的概率。
设 dp[i][j] 表示卡池中有i张牌,手上有j张单牌, 到达目标还要多少步。
转移方程: dp[i][j] = p1 * (dp[i - 1][j] + 1)[抽到的牌不能与手中单排凑成对子]  + p2 * (dp[i - 1][j - 2] + 1)[抽到的牌能与手中单排凑成对子];
其中 p1 = (i - 3 * j) / i, p2 = (3 * j) / i;
当手中的单牌数量为0时为目标状态 dp[i][j] = 0;
*/
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <iostream>
#include <map>
#define int long long
using namespace std;
const int mod = 1e9 + 7;
int dp[200][20];
map<string, int> cnt;
int qmi(int a, int b)
{
    int res = 1 % mod;
    while (b)
    {
        if (b & 1)
        {
            res = (res * a) % mod;
        }
        a = (a * a) % mod;
        b >>= 1;
    }
    return res % mod;
}
int inv(int x)
{
    return qmi(x, mod - 2);
}
/* 卡池中有i张牌,手上有j张单牌 */
int dfs(int i, int j)
{
    if (dp[i][j] != -1)
    {
        return dp[i][j];
    }
    /*已经达到目标状态*/
    if (j == 0)
    {
        return 0;
    }
    int p1 = ((i - 3 * j) % mod * inv(i) % mod) % mod;
    int p2 = ((3 * j) % mod * inv(i) % mod) % mod;
    if (j < 2)
    {
        dp[i][j] = (p1 * (dfs(i - 1, j) + 1) % mod + p2 * 1 % mod) % mod;
    }
    else
    {
        dp[i][j] = (p1 * (dfs(i - 1, j) + 1) % mod + p2 * (dfs(i - 1, j - 2) + 1) % mod) % mod;
    }
    return dp[i][j];
}
signed main()
{
    int T;
    cin >> T;
    int tt = 0;
    for(int i = 0; i < 200; i ++){
        for(int j = 0; j < 20; j ++){
            dp[i][j] = -1;
        }
    }
    while (T--)
    {
        cnt.clear();
        string s;
        cin >> s;
        for (int i = 0; i < 13; i++)
        {
            string c = "";
            c += s[2 * i];
            c += s[2 * i + 1];
            cnt[c]++;
        }
        /*摸牌之后的单牌个数*/
        int n = 0;
        for (auto it : cnt)
        {
            if (it.second == 1)
            {
                n++;
            }
        }
        cout << "Case #" << ++tt << ": " << dfs(123, n) % mod << endl;
    }
}

J Serval and Essay

#include <iostream>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <vector>
#include <set>
#define int long long
using namespace std;
typedef pair<int, int> PII;
const int N = 5e5 + 10;
int n;
int p[N], s[N];
set<int> pre[N], ne[N];
int find(int x)
{
    if (p[x] != x)
    {
        p[x] = find(p[x]);
    }
    return p[x];
}
void merge(int x, int y)
{
    x = find(x);
    y = find(y);
    if(x == y){
        return ;
    }
    // 保证 x 是较大
    if (ne[x].size() < ne[y].size())
    {
        swap(x, y);
    }
    // 把y合并到x上
    p[y] = x;
    s[x] += s[y];

    vector<PII> g;
    for (auto t : ne[y])
    {
        pre[t].insert(x);
        ne[x].insert(t);
        pre[t].erase(y);
        if (pre[t].size() == 1)
        {
            g.push_back({t, x});
        }
    }
    for (auto t : g)
    {
        merge(t.first, t.second);
    }
}
signed main()
{
    int T, tt = 0;
    scanf("%lld", &T);
    while (T--)
    {
        scanf("%lld", &n);
        for (int i = 0; i <= n; i++)
        {
            p[i] = i;
            s[i] = 1;
            pre[i].clear();
            ne[i].clear();
        }

        for (int i = 1; i <= n; i++)
        {
            int k;
            cin >> k;
            for (int j = 1; j <= k; j++)
            {
                int x;
                cin >> x;
                ne[x].insert(i);
                pre[i].insert(x);
            }
        }
        for (int i = 1; i <= n; i++)
        {
            if (pre[i].size() == 1){
                merge(*pre[i].begin(), i);
            }
        }
        int res = 0;
        for (int i = 1; i <= n; i++)
        {
            res = max(res, s[i]);
        }
        cout << "Case #" << ++tt << ": " << res << endl;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值