CURL的使用详解

嵌入式系统及应用——bin/hex/srec烧录文件

  返回  

UCF Local Programming Contest Round 1A 训练联盟暑假场1 题解

2021/7/21 12:00:41 浏览:

UCF Local Programming Contest Round 1A 训练联盟暑假场1 题解

😊 | Powered By HeartFireY | UCF Local Programming Contest Round 1A Solution

A.Briefcases Full of Money

😀 | 知识点:“打字速度”

链接:https://ac.nowcoder.com/acm/contest/18428/A

求成绩最大值对应的因数。

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

int a[8] = {0, 1, 5, 10, 20, 50, 100, 200};
int bmax = 0, imax = 0;

signed main(){
    for(int i = 1; i <= 6; i++){
        int tmp; cin >> tmp;
        if(tmp * a[i] >= bmax * a[imax]) imax = i, bmax = tmp;
    }
    cout << a[imax] << endl;
    return 0;
}

B.A Game Called Mind

😀 | 知识点:思维

链接:https://ac.nowcoder.com/acm/contest/18428/B

题目描述

This problem deals with a simplified version of a game called “Mind”. In this game, a group tries to cooperatively solve a problem. Assume:
- There are 2-6 players (called A, B, C, D, E, F).
- Each player has 1-9 cards in sorted order.
- Each card value is between 10 and 99 (inclusive).

- There are no duplicate values, i.e., a card (number) is in at most one hand.

The objective of the game is for all the players to put all the cards down in sorted order (in the real game, players do not see their own cards, hence the name for the game – Mind). Given the cards in each hand, you are to provide the order for the players to place their cards down.

输入描述:

The first input line contains an integer, p (2 ≤ p ≤ 6), indicating the number of players. Each of  the following p input lines provides the cards for one player. Each line starts with an integer, c (1 ≤ c ≤ 9), indicating the number of cards for that player; the count is followed by the cards in sorted order (each card between 10 and 99, inclusive).

输出描述:

Print the order for the players to place down the cards so that the cards are in order.

解决方案

题目给定2-6名玩家的卡牌,要求输出按照牌面大小顺序出牌的玩家序列。

思路,给每张卡牌标记所属的人,然后整体排序输出即可。

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

struct poke{
    int val, player;
    bool operator < (struct poke a){ return val < a.val; }
}poke[1000];

char mp[] = {'A', 'B', 'C', 'D', 'E', 'F'};

signed main(){
    int t = 0, sum = 0; cin >> t;
    for(int i = 0; i < t; i++){
        int n = 0; cin >> n;
        for(int j = 0; j < n; j++){
            cin >> poke[sum].val;
            poke[sum++].player = i;
        }
    }
    sort(poke, poke + sum);
    for(int i = 0; i < sum; i++) 
        cout << mp[poke[i].player];
    cout << endl;
    return 0;
}

C.Unique Values

😀 | 知识点:双指针

链接:https://ac.nowcoder.com/acm/contest/18428/C

题目描述

Arup has to make many practice questions for his Computer Science 1 students. Since many of the questions deal with arrays, he has to generate arrays for his students. Since he doesn’t want to give them difficult practice problems, he always guarantees that the arrays (given to the students) have unique values. Namely, no value will appear twice in any of his arrays.

Unfortunately, Arup is too lazy to generate arrays! About 20 years ago when he started teaching Computer Science 1, he made one really long array to reuse but this long array may have duplicate values. When he makes problems, he simply grabs a contiguous subsequence of this long array to be the array to be used for a problem but he needs to make sure the contiguous subsequence does not contain duplicates. If the long array has terms a[0], a[1], …, a[n-1], a contiguous subsequence of the long array is any sequence of j – i + 1 terms a[i], a[i+1], …, a[j] where 0 ≤ i ≤ j ≤ n – 1.

The Problem: Given an array of n integers, determine how many contiguous subsequences of the array do not contain any repeated values. Note that two subsequences with the same contents are considered different (i.e., both counted in the total) if they start at different locations of the original long array.

输入描述

The first input line contains a single positive integer, n (1 ≤ n ≤ 105 ), representing the size of the input array. The following line contains n space separated integers, representing the values of the input array, in the order they appear in the array. Each of the array values will be an integer between 1 and 109 , inclusive.

输出描述:

On a line by itself, output the total number of contiguous subsequences of the input array that do not contain any repeated values

解决方案

题目要求求区间内元素不重复的连续子序列个数,那么策略很简单,找出不重复的区间并计数即可。

如何找出不重复的区间?

我们设置一个集合和 l o w 、 h i g h low、high lowhigh指针,初始状态 l o w 、 h i g h low、high lowhigh指针指向 0 0 0位置, h i g h high high指针作为右端点向右逐个遍历。集合用于统计每个元素出现的次数,每次high指针遍历到新元素,要向集合插入元素前判断元素是否已经存在,若存在则擦除一次, l o w low low指针向右移动一次。借助例子理解:如图所示

在这里插入图片描述

假设 h i g h high high指针遍历到第 1 1 1个元素 a [ 1 ] = 1 a[1] = 1 a[1]=1(下标从 0 0 0开始),此时检测集合中已经存在该元素,那么集合擦除一次 1 1 1 l o w low low指针后移至 1 1 1,同时再向集合中插入新元素 a [ 1 ] a[1] a[1]

插入完成后,以当前 l o w low low指针指向元素为起点, h i g h high high指针指向元素为终点的区间子序列个数就是 l o w − h i g h + 1 low - high + 1 lowhigh+1,如此往复统计,直至遍历完毕即可。

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

const int N = 1e5 + 10;
ll val[N], ans = 0, l = 0;

signed main(){
    int n = 0; cin >> n;
    for(int i = 0; i < n; i++) cin >> val[i];
    set<int> s;
    for(int h = 0; h < n; h++){
        while(s.count(val[h]) == 1) s.erase(val[l++]);
        s.insert(val[h]);
        ans += (h - l + 1);
    }
    cout << ans << endl;
    return 0;
}

D.Gone Fishing

😀 | 知识点:计算几何基础

链接:https://ac.nowcoder.com/acm/contest/18428/D

题目给出一堆点的坐标,给定一个圆的半径,移动该圆的位置,使其尽可能多的覆盖点,求最大覆盖点的数量。

WA了5发,全都是因为考虑不周全QAQ。

先说答题思路,题目数据范围很小,因此只需要两个点依次枚举,计算过该两个点,以R为半径的圆的圆心坐标,再遍历点集,找出位于园内的点计数,取最大值即可。三重循环 O ( N 3 ) O(N^3) O(N3),对于所给出局范围完全能行。

求圆心坐标的时候,坑点格外多,首先要注意过两点定半径的圆心有两个(两侧的圆心坐标不同),因此要分开统计,其次按照传统方法求圆心坐标的时候,额外注意考虑横坐标相同的情形(此时直接算会出现分母为 0 0 0导致 N A N NAN NAN无法计算而漏点)。

在这里插入图片描述

AC CODE:

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

const int N = 100 + 10;
const double JD = 0.0000001;

typedef pair<double, double> pdd;

inline double getdis(double x1 ,double y1, double x2, double y2){ return (double)sqrt((x2 - x1) * (x2 - x1) + (y2 - y1) * (y2 - y1)); }

pdd point[N];

inline void getcirclecenter(double x1, double y1, double x2, double y2, double R, double &xx1, double &yy1, double &xx2, double yy2){
    if(x2 == x1){
        xx1 = x1 + sqrt(R * R - ((y2 - y1) * (y2 - y1) / 4)), yy1 = (y2 + y1) * 0.5, xx2 = x1 - sqrt(R * R - ((y2 - y1) * (y2 - y1) / 4)), yy2 = yy1;
        return;
    }
    double x, y;
    double c1 = (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) / (2 * (x2 - x1));
    double c2 = (y2 - y1) / (x2 - x1);
    double A = (c2 * c2 + 1), B = (2 * x1 * c2 - 2 * c1 * c2 - 2 * y1), C = x1 * x1 - 2 * x1 * c1 + c1 * c1 + y1 * y1 - R * R;
    yy1 = (-B + sqrt(B * B - 4 * A * C)) / (2 * A);
    xx1 = c1 - c2 * yy1;
    yy2 = (-B - sqrt(B * B - 4 * A * C)) / (2 * A);
    xx2 = c1 - c2 * yy2;
} 

signed main(){
    double r = 0; cin >> r;
    int n = 0; cin >> n;
    int ans = 0;
    for(int i = 0; i < n; i++) cin >> point[i].first >> point[i].second;
    for(int i = 0; i < n; i++){
        for(int j = i + 1; j < n; j++){
            if(getdis(point[i].first, point[i].second, point[j].first, point[j].second) > 2 * r) continue;
            double ncx1, ncy1, ncx2, ncy2;
            getcirclecenter(point[i].first, point[i].second, point[j].first, point[j].second, r, ncx1, ncy1, ncx2, ncy2);
            int tans1 = 0, tans2 = 0;
            for(int k = 0; k < n; k++){
                //if(k == i || k == j) continue;
                double dis1 = getdis(ncx1, ncy1, point[k].first, point[k].second) - r;
                double dis2 = getdis(ncx2, ncy2, point[k].first, point[k].second) - r;
                if(dis1 < JD) tans1++;
                if(dis2 < JD) tans2++;
            }
            ans = max(max(tans1, tans2), ans);
        }
    }
    ans = max(ans, 1);
    cout << ans;
    return 0;
}

E.Sum of a Function

😀 | 知识点:素数筛、容斥原理

链接:https://ac.nowcoder.com/acm/contest/18428/E

题目描述

输入描述

输出描述

题目分析

给定函数 f ( n ) f(n) f(n)​​为求给定 n n n​​​​的最小质因数,现在要求给定 s 、 e s、e se​​,求出 x ∈ [ s , e ] x \in [s, e] x[s,e]使得 f ( x ) f(x) f(x)为倒数后 k k k小的值时, f ( x ) f(x) f(x)之和。

首先观察数据范围 K ∈ [ 1 , 0.9 × ( e − s + 1 ) ] K \in [1, 0.9 \times(e - s + 1)] K[1,0.9×(es+1)]​, e − s ≤ 1 e 6 e - s \leq 1e6 es1e6,我们不可能会用到区间内全部的数字,只需要前 k k k小的即可,因此可以先筛 1 e 6 1e6 1e6范围内的素数,对于大数区间就可以使用区间筛解决。

为什么只需要筛 1 e 6 1e6 1e6范围内的素数?

利用容斥原理(或乘法原理)可知, 1 e 6 1e6 1e6​以内的质数足以将一个区间覆盖到$90 % $$(r=(1-1/2)(1-1/3)(1-1/5)(1-1/7)(1-1/11)… ,r 表 示 未 被 覆 盖 的 占 比 ) , 且 未 被 覆 盖 到 的 点 , 函 数 值 表示未被覆盖的占比),且未被覆盖到的点,函数值 )f$大于 1 e 6 1e6 1e6​​。

r r r​的计算:对于区间内的数字,我们采用以下形式进行表示:
自 然 数 : n 2 的 倍 数 : 2 n 3 的 倍 数 : 3 n 4 的 倍 数 : 4 n . . . . . . \begin{aligned} &自然数:n \\ &2的倍数:2n \\ &3的倍数:3n\\ &4的倍数:4n\\ &...... \end{aligned} :n2:2n3:3n4:4n......

那么很容易知道各倍数出现的概率分别为:
自 然 数 : 1 2 的 倍 数 : 1 2 3 的 倍 数 : 1 3 4 的 倍 数 : 1 4 . . . . . . \begin{aligned} &自然数:1 \\ &2的倍数:\frac12 \\ &3的倍数:\frac13\\ &4的倍数:\frac14\\ &...... \end{aligned} :12:213:314:41......
这些数字出现的概率可以得出区间内非质数的覆盖率,根据容斥原理可以知道 ( 1 − p ) (1 - p) (1p)为非 1 p \frac1p p1​倍数出现的概率,可求得区间质数的覆盖率: r = ( 1 − 1 / 2 ) ∗ ( 1 − 1 / 3 ) ∗ ( 1 − 1 / 5 ) ∗ ( 1 − 1 / 7 ) ∗ ( 1 − 1 / 11 ) . . . . ≈ 90 % r=(1-1/2)*(1-1/3)*(1-1/5)*(1-1/7)*(1-1/11).... ≈ 90\% r=(11/2)(11/3)(11/5)(11/7)(11/11)....90%

又因为 K ∈ [ 1 , 0.9 × ( e − s + 1 ) ] K \in [1, 0.9 \times(e - s + 1)] K[1,0.9×(es+1)],可以知道要求的 K K K​个数字可以满足。

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

const int MAXN = 1e6 + 1010;

ll prime[MAXN], isp[MAXN], res[MAXN], cnt = 0;

void init(){
    for(int i = 2; i < MAXN; i++){
        if(!isp[i]) prime[++cnt] = i;
        for(int j = 1; j <= cnt && i * prime[j] < MAXN; j++){
            isp[prime[j] * i] = 1;
            if(i % prime[j] == 0) break;
        }
    }
}

void solve(ll l, ll r){
    for(int i = 0 ; i < r - l + 1; i++) res[i] = i + l;
    for(int i = 1; i <= cnt; i++){
        ll s = l / prime[i];
        if(s <= 1) s = 2;
        for(ll j = s * prime[i]; j <= r; j += prime[i]){
            if(j >= l){
                if(res[j - l] == j) res[j - l] = prime[i]; 
            } 
        }
    }
}

signed main(){
    init();
    int s, e, k; cin >> s >> e >> k;
    solve(s, e);
    sort(res, res + e - s + 1);
    ll sum = 0;
    for(int i = 0; i < k; i++) sum += res[i];
    cout << sum << endl;
    return 0;
}

F.Hang Gliding

😀 | 知识点:DP动态规划

链接:https://ac.nowcoder.com/acm/contest/18428/F

题目描述

The 2020 hang gliding world championships are coming to Florida next spring! (You may think it is odd to hold in Florida a sport that requires mountains, but it turns out that hang gliders can be towed to altitude by other aircraft.) The competition is divided into a set of tasks; completing a task successfully gives a pilot a number of points. Either all points are awarded for a task, or none are. For each task, every pilot has a probability of success. A pilot’s score is the total of all successfully completed tasks at the end of the competition.

This year, the organizing committee couldn’t decide on a reasonable number of tasks, so the time slots for tasks overlap. At any given time, there can be multiple tasks going on, but a pilot may only choose one to be competing in at that time. Each pilot may compete in as many tasks as they want given this constraint. The pilots know their own strengths and weaknesses, and will choose tasks in order to maximize their expected score.

You have been offered free hang gliding lessons if you help with scoring software for the event. Among other things, the committee wants the software to be able to predict the winners ahead of time. Given a set of tasks, each with a time slot and a point score to be awarded for success, and a list of pilots, each with success probabilities for each task, compute the expected score for each pilot, and report the top 3 expected scores.

输入描述

The first input line contains two integers: t (1 ≤ t ≤ 10000), indicating the number of tasks, and p(3 ≤ p ≤ 100), indicating the number of pilots.

The next t input lines contain the task descriptions. Each line contains three integers (s, e, and a) separated by a space: 0 ≤ s < e ≤ 10000, s is the start time of the task, and e e e is the end time of the task, in minutes after the competition starts; a (1 ≤ a ≤ 100) is the number of points awarded for the task. Note that the task start times and end times are non-inclusive, i.e., if a task ends at time T and another task starts at time T, a pilot can compete in both tasks.

After the task descriptions, there are t lines for each pilot. The first t lines in this section are the probabilities of success for each task for pilot 1; the next t lines are the probabilities of success for pilot 2, and so on. The probabilities are floating point numbers in the range 0 to 1, inclusive.

输出描述

Print the top 3 pilots. Print, in order of descending expected score, the pilot’s number, a space, and the pilot’s expected score, rounded to 2 decimal places (i.e., a score of 42.494 would be printed as 42.49; a score of 42.495 would be printed as 42.50). Note that pilots are numbered starting at 1, not zero.

题目分析

给定 t t t​个任务、 p p p​个选手:

  1. 每场考试具有三个参数 s 、 e 、 a s、e、a sea​​​分别表示任务开始的时间、结束的时间、任务的分数上限;
  2. 给定的第 i i i​组数据,代表第 i i i​个选手第 j j j​​个任务上能取得分数占总分数的百分比。

求成绩最好的三个同学的序号和总分。

由于任务时间存在冲突,因此对于每个选手需要对参加的任务进行取舍,首先作出第二组样例的时间轴:

在这里插入图片描述

很明显,这个问题属于带权值的活动选择问题:

  • 含有重叠子问题
  • 有最优解使总的收益最大

如何解决这类问题?

首先我们知道,活动必须一个结束后,另外一个才能开始。因此我们需要先对活动按照结束的时间先后顺序进行排序。然后从第一个活动开始遍历这些任务,同时维护一个全局最大值,到每个活动结束的最大值。排序时间复杂度为 O ( n l o g n ) O(nlogn) O(nlogn),后面一段时间复杂度为 O ( n ) O(n) O(n)

此类问题的状态转移方程一般为 A n s = m a x ( A n s ,   l a s t + e d g e s [ i ] . v a l ) ; Ans = max(Ans,\ last + edges[i].val); Ans=max(Ans, last+edges[i].val);​​​​其中, A n s Ans Ans​为全局最大值, l a s t last last​​​为截止到上一个和本任务不产生冲突的任务所保存的最大值。

在本题目中的转移方程: m e m o [ j ] = m a x ( e x p e c t e d [ i ] [ t a s k s [ j ] . s e r i a l ] + m e m o [ p r e [ j ] ] , m e m o [ j − 1 ] ) memo[j] = max(expected[i][tasks[j].serial] + memo[pre[j]], memo[j - 1]) memo[j]=max(expected[i][tasks[j].serial]+memo[pre[j]],memo[j1]),其中 p r e pre pre​数组需要提前构造,表示​不冲突任务的先后关系。

AC CODE:

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

const int maxn = 10000 + 10;
const int maxp = 100 + 10;

struct task{
    int start, end, points, serial;
    task(int ss = 0, int ee = 0, int pp = 0, int se = 0): start(ss), end(ee), points(pp), serial(se) {};
    const int operator< (const task &a){ return end < a.end; }
}tasks[maxn];

int pre[maxn], ranks[maxp];
double expected[maxp][maxn], memo[maxn], predsc[maxp];

signed main(){
    ios_base::sync_with_stdio(false);
    int t, p; cin >> t >> p;
    for(int i = 1; i <= t; i++){
        cin >> tasks[i].start >> tasks[i].end >> tasks[i].points;
        tasks[i].serial = i;
    }

    for(int i = 0; i < p; i++){
        for(int j = 1; j <= t; j++){
            cin >> expected[i][j];
            expected[i][j] *= tasks[j].points;
        }
    }

    sort(tasks + 1, tasks + 1 + t);

    for(int i = 1; i <= t; i++){
        pre[i] = 0;
        for(int j = i - 1; j > 0; j--){
            if(tasks[j].end <= tasks[i].start){
                pre[i] = j;
                break;
            }
        }
    }

    for(int i = 0; i < p; i++){
        memo[0] = 0.0;
        for(int j = 1; j <= t; j++)
            memo[j] = max(expected[i][tasks[j].serial] + memo[pre[j]], memo[j - 1]);
        predsc[i] = memo[t];
        ranks[i] = i;
    }

    sort(ranks, ranks + p, [&](int i, int j){ return predsc[i] > predsc[j]; });

    for(int i = 0; i < min(p, 3); i++) cout << ranks[i] + 1  << ' ' << fixed << setprecision(2) << predsc[ranks[i]] << endl;
    return 0;
}

联系我们

如果您对我们的服务有兴趣,请及时和我们联系!

服务热线:18288888888
座机:18288888888
传真:
邮箱:888888@qq.com
地址:郑州市文化路红专路93号