UCF Local Programming Contest Round 1A A~F题解

题目链接:点这里

A.Briefcases Full of Money

  • 题意

分别对应数量的面值币,请你选择总和金额最大的币的面值。如果存在相同的,输出面值最大的。

  • 解题思路
    水题,直接取出最大值即可。

  • AC代码

/**
  *@filename:A
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-21 21:07
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int a[7],b[7] = {0,1,5,10,20,50,100};
void solve(){
    int maxx = a[1], pos = 1;
    for(int i = 2; i <= 6; ++ i){
        if(a[i] >= maxx){
            maxx = a[i];
            pos = i;
        }
    }
    cout << b[pos] << endl;
}
int main(){
    for(int i = 1; i <= 6; ++ i){
        cin >> a[i];
        a[i] *= b[i];
    }
    solve();
    return 0;
}

B.A Game Called Mind

  • 题意
    有 p p p个玩家,每个玩家有 c i c_i ci​张卡片,分别有一个权值,按权值排列输出拥有这张卡片的玩家。

  • 解题思路
    利用pair对,first存储卡片权值,second存储拥有这张卡片的玩家序号,排序即可。

  • AC代码

/**
  *@filename:B
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-21 21:14
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int p,c,x;
vector<pair<int,int> > v;
void solve(){
    sort(v.begin(), v.end());
    for(auto &iter : v){
        cout << (char)(iter.second + 'A');
    }
    cout << endl;
}
int main(){
    cin >> p;
    for(int i = 0; i < p; ++ i){
        cin >> c;
        for(int j = 0; j < c; ++ j){
            cin >> x;
            v.push_back({x,i});
        }
    }
    solve();
    return 0;
}

C.Unique Values

  • 题意
    给你一个序列,需要你计算出所有连续子序列中没有出现重复元素的总序列个数。

  • 解题思路
    首先我们知道,对于一个未出现重复元素的序列,其真子序列必定也是扶额和要求的,所以我们如果找到了一个最长的未出现重复元素的序列,那么其方案我们可以记作其长度,从而不用考虑它的子序列了。 所以,我们可以利用双指针,去寻找这符合要求的最长子序列,为了判断是否出现重复元素,我们利用hasSet可以实现,记得在指针移动过程中需要及时插入新元素和剔除过期元素即可。

  • AC代码

/**
  *@filename:C
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-21 21:24
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 5;
const int P = 1e9+7;

int n;
ll a[N];
unordered_set<ll> t;//set存放。
void solve(){
    ll ans = 0;
    int l = 1, r = 1;
    while(l <= r){
        while(r <= n && !t.count(a[r])){
            t.insert(a[r]);
            r ++;
        }
        ans += r - l;
        t.erase(a[l]);
        l ++;
    }
    cout << ans << endl;
}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; ++ i){
        scanf("%d", &a[i]);
    }
    solve();
    return 0;
}

D.Gone Fishing

  • 题意
    给你一个可以移动的半径为 r r r的圆和 n n n个点,需要你判断出该圆最多可以覆盖多少个点。

  • 解题思路
    按照贪心原则,为了极大的覆盖区域,我们必定会选择两个点在圆上,这样就可以唯一确定一个圆。所以我们可以枚举这两个点,从而计算出圆心的位置。最后统计符合要求的最大点数即可。

  • 解题思路

/**
  *@filename:D
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-22 18:49
**/
#include <bits/stdc++.h>
#define x first
#define y second

using namespace std;

typedef long long ll;
typedef pair<double,double> pdd;
const int N = 100000 + 5;
const double EPS = 1e-8;
const int P = 1e9+7;

double r;
int n;
pdd points[110];
double getDist(pdd a,pdd b){
    return sqrt((a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y));
}
pdd getCenter(pdd a, pdd b){
    pdd mid = {(a.x + b.x) / 2, (a.y + b.y) / 2};
    double w = atan2(a.x - b.x,b.y - a.y);//计算正切值。
    double d = sqrt(r * r - getDist(a,mid) * getDist(a,mid));
    return {mid.x + d * cos(w),mid.y + d * sin(w)};
}
void solve(){
    int maxx = 1;
    for(int i = 1; i <= n; ++ i){
        for(int j = i + 1; j <= n; ++ j){
            if(getDist(points[i],points[j]) > 2 * r)continue;
            pdd cen = getCenter(points[i],points[j]);
            int cnt = 0;
            for(int k = 1; k <= n; ++ k){
                if(getDist(points[k],cen) < r + EPS)cnt ++;//注意精度问题,在计算过程中可能会损失精度,我们需要加上一个精度控制。
            }
            maxx = max(cnt,maxx);
        }
    }
    cout << maxx << endl;
}
int main(){
    cin >> r;
    cin >> n;
    for(int i = 1; i <= n; ++ i){
        cin >> points[i].x >> points[i].y;
    }
    solve();
    return 0;
}

E.Sum of a Function

  • 题意
    定义函数 F ( x ) F(x) F(x)为 x x x的最小素因子,给定一个区间 [ l , r ] [l,r] [l,r],求出其中前 k k k小的 F ( x ) F(x) F(x)总和。

  • 解题思路
    看到这个题,注意到 l , r l,r l,r的数据范围,如果我们直接筛素数,是不可能实现的。这道题和 P O J POJ POJ上的Prime Distance题目很像,都是利用偏移,通过剔除素数因子来实现的。我们知道由于 k k k是只占区间的 90 % 90\% 90%,而 2 n , 3 n , 5 n , 7 n . . . 2n,3n,5n,7n... 2n,3n,5n,7n...我们通过素数因子筛掉的数就足足有 90 % 90\% 90%。所以我们的思路是直接筛出 1 e 6 1e6 1e6以内的素数。然后通过筛出的素数,去确定其区间中的数的最小素数因子即可,注意区间偏移。

  • AC代码

/**
  *@filename:E
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-22 10:55
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 1000000 + 5;
const int P = 1e9+7;

bool notPrimer[N];
int primer[N];
ll l,r,k,res[N];
void init(){
    for(int i = 2; i < N; ++ i){
        if(!notPrimer[i]){
            primer[++ primer[0]] = i;
            
        }
        for(int j = 1; j <= primer[0] && i * primer[j] < N; ++ j){
            notPrimer[i * primer[j]] = true;
            if(i % primer[j] == 0)break;//说明碰到了素因子,直接退出。
        }
    }
}
void solve(){
    init();
    for(int i = 0; i < r - l + 1; ++ i){
        res[i] = l + i;//平移区间。
    }
    for(int i = 1; i <= primer[0]; ++ i){
        if(primer[i] >= r)break;
        ll temp1 = (l - 1) / primer[i] + 1;
        if(temp1 == 1)temp1 = 2;
        ll temp2 = r / primer[i];
        for(ll j = temp1; j <= temp2 && j * primer[i] <= r; ++ j){
            if(res[j * primer[i] - l] == j * primer[i]){
                res[j * primer[i] - l] = primer[i];
                //cout << j * primer[i] << " " << primer[i] << endl;
                //cout << primer[i] << " ";
            }
        }
    }
    sort(res,res + r - l + 1);
    ll sum = 0;
    for(int i = 0; i < k; ++ i){
        sum += res[i];
    }
    cout << sum << endl;
}
int main(){
    cin >> l >> r >> k;
    solve();
    return 0;
}

F.Hang Gliding

  • 解题思路
    给你一系列任务的信息,现在需要你确定每个玩家能获得的最大分数。

  • 解题思路
    由于每个玩家都是互相独立的,所以我们可以分开计算。对于每个玩家,这个任务可以做或者不做,这类似于背包问题,如果做了这个任务,那么这段时间内就不可以做别的任务;如果没有做这个任务,那么最大分数就和上个状态一样。我们来确定一下状态,设 d p [ j ] dp[j] dp[j]为遍历到第 j j j个任务的最大分数,那么 d p [ j ] = m a x ( d p [ j − 1 ] , d p [ 第 j 个 任 务 开 始 前 最 晚 完 成 的 任 务 ] + s c o r e [ j ] dp[j] = max(dp[j - 1],dp[第j个任务开始前最晚完成的任务] + score[j] dp[j]=max(dp[j−1],dp[第j个任务开始前最晚完成的任务]+score[j]。据此,则可以解决。注意纪录任务的下标。还有一个值得注意的点,这种任务序列,决定其的永远是结束时间,而不是开始时间。

  • AC代码

/**
  *@filename:F
  *@author: pursuit
  *@csdn:unique_pursuit
  *@email: 2825841950@qq.com
  *@created: 2021-07-22 19:39
**/
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 10000 + 5;
const int P = 1e9+7;

int n,m;//飞行员数量和任务数。
struct node{
    double st,ed,score;
    int pos;
    bool operator < (node A){
        if(ed == A.ed){
            return st < A.st;
        }
        return ed < A.ed;
    }
}tasks[N];
double stu[110][N];
double score[110][N];
struct node1{
    double score;
    int pos;
    bool operator < (const node1 A){
        return score > A.score;
    }
}result[N];
int cal(int r, double x){
    int l = 1;
    while(l <= r){
        int mid = (l + r) >> 1;
        //cout << "l:" << l << " r:" << r << endl;
        if(tasks[mid].ed <= x){
            l = mid + 1;
        }
        else{
            r = mid - 1;
        }
    }
    return r;
}
void solve(){
    sort(tasks + 1, tasks + 1 + m);
    for(int i = 1; i <= n; ++ i){
        double maxx = 0;
        for(int j = 1; j <= m; ++ j){
            score[i][tasks[j].pos] = max(score[i][tasks[j - 1].pos], score[i][tasks[cal(j - 1,tasks[j].st)].pos] + stu[i][tasks[j].pos]);
            maxx = max(maxx, score[i][tasks[j].pos]);
        }
        result[i].score = maxx;
        result[i].pos = i;
    }
    sort(result + 1, result + 1 + n);
    for(int i = 1; i <= 3; ++ i){
        printf("%d %.2lf\n", result[i].pos, result[i].score);
    }
}
int main(){
    scanf("%d%d", &m, &n);
    for(int i = 1; i <= m; ++ i){
        scanf("%lf%lf%lf", &tasks[i].st, &tasks[i].ed, &tasks[i].score);
        tasks[i].pos = i;
    }
    for(int i = 1; i <= n; ++ i){
        for(int j = 1; j <= m; ++ j){
            scanf("%lf", &stu[i][j]);
            stu[i][j] *= tasks[j].score;
        }
    }
    solve();
    return 0;
}
上一篇:UCF Local Programming Contest Round 1A(题解)


下一篇:义乌集训7.12 contest 5题解