UCF Local Programming Contest Round 1A 【2021-7-20】

UCF Local Programming Contest Round 1A 【2021-7-20】

题目链接

A题和B题纯签到就不放了~
训练联盟的第一场!!可做的题还是挺多的。DP,计算几何,线段树,双指针……
最近天气不错!冲鸭~

C.Unique Values

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[0], a[1], …, a[n-1] a[0],a[1],,a[n1], a contiguous subsequence of the long array is any sequence of j-i+1 terms a [ i ] , a [ i + 1 ] , … , a [ j ] a[i], a[i+1], …, a[j] a[i],a[i+1],,a[j] where 0 ≤ i ≤ j ≤ n – 1 0 ≤ i ≤ j ≤ n – 1 0ijn1.

Given an array of n n 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 ≤ 1e5), 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 1e18, inclusive.

(Note: 1e5 means 1 times 10 to the fifth power, that is, 100000)

输出描述

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

示例一

输入

5
1 1 2 1 5

输出

9

示例二

输入

8
2 12 3 12 3 2 6 9

输出

22

解题思路

题目解读:给出n个元素的数组,要求可以取多少个连续不重复的子序列。
思路分析:刚开始看这题有好多人A了,但是我们还是没有什么思路,A了D之后,半猜半做过了。这个是双指针问题,我们维护的是一段不重复的序列,因此我们在尾端标记一个指针,遇到相同时,把指针移到当前这个位置。

Code

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

map<LL,LL>ma;
const int maxn=1e5+10;
int main(){
    LL n,a[maxn];
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    LL res=0,j=0;
    for(int i=1;i<=n;i++){
        if(ma[a[i]]){ //如果在队列中已经存在过
            j=max(ma[a[i]],j); //指针移动
        }
        res+=i-j;
        ma[a[i]]=i;
    }
    cout<<res<<endl;

    return 0;
}

D.Gone Fishing

t t t is getting dark and the mosquitoes are attacking Fisherman Floyd. Floyd decides to throw his circular net one last time and wants to make the most out of the last throw.

Given the size (radius) of Floyd’s net and positions ( x , y ) (x,y) (x,y) of a set of fish, what is the maximum fish Floyd can catch with one throw? That is, find the maximum points you can have in the net (circle). If a point (fish) is within 1 0 − 6 10^{-6} 106 of the circle boundary, consider the point in the circle.

输入描述

The first input line provides the radius of the circle. The second input line contains an integer, n ( 1 ≤ n ≤ 100 ) n (1 ≤ n ≤ 100) n(1n100), indicating the number of fish. Each of the next n input lines provides the location ( x , y ) (x,y) (x,y) for one fish.

Assume all these points are distinct. Also assume that all the x x x and y y y values in the input (as well as the circle radius) are integers between 1 1 1 and 1000 1000 1000, inclusive.

输出描述

Print the maximum fish Floyd can catch with one throw.

示例一

输入

20
4
6 7
5 5
190 100
4 4

输出

3

示例二

输入

3
2
1 1
95 4

输出

1

解题思路

题目解读:给出了n个坐标以及一个圆的的半径r,该圆的位置可自由确定,求解该圆最多可以包含多少给出的点。
思路分析:很明显的一道计算几何题。看到数据规模只有100,就想到了暴力去做,取任意两点作为该圆的边界弦,这样的圆可以画两个,再根据求出的圆判断有多少点落入这个区间,最后统计一下取max即可。
思路比较清晰,代码的时候难点在于确定这个圆心的位置。
圆心位置的求法:连接两点做垂直平分线,求出垂直平分线的斜率,根据勾股定理求出两点中点到圆心的距离,然后解三角形。
代码有【下面图解含标注】:

void Solve(double x1, double y1, double x2, double y2){
    double dis1=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);
    double e_x=(x1+x2)/2;
    double e_y=(y1+y2)/2;
    double k;
    double ce=r*r-dis1/4.0;
    if (y1==y2){
        c_x=e_x;
        c_y=y1+sqrt(ce);
        d_x=e_x;
        d_y=y1-sqrt(ce);
        return;
    }
    k=(x2-x1)/(y1-y2);

    c_x=e_x-sqrt(ce/(1+k*k));
    c_y=e_y+k*(c_x-e_x);

    d_x=e_x+sqrt(ce/(1+k*k));
    d_y=e_y+k*(d_x-e_x);
}

然后还WA了两发,第一次没有注意到到y1=y2的时候k不存在,需要额外判断,另外就是精度问题!!!感谢队友发现~

Code

#include<bits/stdc++.h>
#define LL long long

const int maxn = 1e5;
using namespace std;

struct Poin{
    double x, y;
}po[maxn];
double r;
int n;

double c_x, c_y, d_x, d_y;
void Solve(double x1, double y1, double x2, double y2){
    double dis1=(x2-x1)*(x2-x1)+(y2-y1)*(y2-y1);  //两点距离
    //cout<<dis1<<" "<<dis2<<endl;

    double e_x=(x1+x2)/2;
    double e_y=(y1+y2)/2;

    //cout<<e_x<<","<<e_y<<endl;

    double k;
    double ce=r*r-dis1/4.0;
    if (y1==y2){
        c_x=e_x;
        c_y=y1+sqrt(ce);
        d_x=e_x;
        d_y=y1-sqrt(ce);
        return;
    }
    k=(x2-x1)/(y1-y2);
    //cout<<ce<<endl;
    c_x=e_x-sqrt(ce/(1+k*k));
    c_y=e_y+k*(c_x-e_x);

    //cout<<sqrt(ce/(1+k*k))<<endl;

    d_x=e_x+sqrt(ce/(1+k*k));
    d_y=e_y+k*(d_x-e_x);
}
int main() {
    cin>>r>>n;
    for(int i=0;i<n;i++) {
        cin>>po[i].x>>po[i].y;
    }

    int res1=0, res2=0, res=0;
    for (int i=0;i<n;i++){
        for (int j=0;j<i;j++){
            double dis=sqrt((po[i].x-po[j].x)*(po[i].x-po[j].x));
            if (dis>2*r) continue;
            Solve(po[i].x, po[i].y, po[j].x, po[j].y);
            res1=res2=0;
            for(int k=0;k<n;k++){
                if(sqrt((c_x-po[k].x)*(c_x-po[k].x)+(c_y - po[k].y)*(c_y-po[k].y))-r<=1e-6) res1++;
            }
            for(int k=0;k<n;k++){
                if(sqrt((d_x-po[k].x)*(d_x-po[k].x)+(d_y-po[k].y)*(d_y-po[k].y))-r<=1e-6) res2++;
            }
            res=max(res,max(res1,res2));
        }
    }
    if(res==0) res=1;
    cout<<res<<endl;
    return 0;
}

E.Sum of a Function

Everyone knows that Arup loves prime numbers! This is why he teaches the cryptography course at UCF. Recently, Arup defined the following function on positive integers, n, greater than 1:

f ( n ) f(n) f(n) = the smallest prime factor of n n n

For example, f ( 14 ) = 2 , f ( 15 ) = 3 , f ( 16 ) = 2 f(14)=2, f(15)=3, f(16)=2 f(14)=2,f(15)=3,f(16)=2 and f ( 17 ) = 17 f(17)=17 f(17)=17.

Using this function, we can generate a sequence of terms f ( s ) , f ( s + 1 ) , f ( s + 2 ) , … , f ( e ) f(s), f(s+1), f(s +2), …, f( e) f(s),f(s+1),f(s+2),,f(e), where s designates the starting function input and e designates the ending function input.

Arup thinks these sequences are interesting, but what he’s really curious about is finding the sum of the k k k minimum elements in one of these sequences. Can you write a program to help him?

Given s s s, e e e, and k k k, find the sum of the k minimum values in the sequence f ( s ) , f ( s + 1 ) , f ( s + 2 ) , … , f ( e ) f(s), f(s+1), f(s +2), …, f(e) f(s),f(s+1),f(s+2),,f(e).

输入

The first and only input line will contain three positive integers, s ( 2 ≤ s ≤ 1018 ) , e ( s + 100 ≤ e ≤ s + 106 ) s(2 ≤ s ≤ 1018 ), e (s +100 ≤ e ≤ s+106 ) s(2s1018),e(s+100es+106), and k ( 1 ≤ k ≤ 0.9 ∗ ( e – s + 1 ) ) k (1 ≤ k ≤ 0.9 * (e – s + 1)) k(1k0.9(es+1)), representing (respectively) the starting function input, the ending function input, and the number of minimum terms to sum.

输出

On a line by itself, print the sum of the k minimum terms of the designated sequence.

示例一

输入

100 200 70

输出

165

示例二

输入

213 419 169

输出

546

解题思路

题意解读:简单概括一下就是输出 s s s e e e之间第 k k k个最小质数因子。
思路分析:首先想到区间大数筛,区间大数筛也就是数组下标发生了偏移,然后sort一下。写的时候一直段错误。后来看了题解,重新构思了一下,S~E是连续的,中间有2的倍数,3的倍数,5的倍数等等,由于S到E最多 1 0 6 10^6 106,所以直接筛了。用试除法求约数,求出最小的那个约数就可break。试了最大的数据 1 0 18 10^{18} 1018, k = 900000 k=900000 k=900000时,第k小的数为257,因此我们求约数时除数取到300绰绰有余。

Code

#include<bits/stdc++.h>
#define LL long long

using namespace std;
const int maxn=1e6+10;
LL a[maxn],idx;

int main(){
    LL s,e,k,ans=0;
    cin>>s>>e>>k;
    for(LL i=s;i<=e;i++){   //这里要记得开long long
        LL tmp=i;
        for(int j=2;j<=300;j++){ //这里300就够了
            if(tmp%j==0){
                cout<<"a["<<idx<<"]="<<j<<endl;
                a[idx++]=j;
                break;
            }
        }
    }
    sort(a,a+idx);
    for(int i=0;i<k;i++){
        ans+=a[i];
    }
    cout<<ans<<endl;
    return 0;
}

F.Hang Gliding

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 ) t (1 ≤ t ≤ 10000) t(1t10000), indicating the number of tasks, and p ( 3 ≤ p ≤ 100 ) p(3 ≤ p ≤ 100) p(3p100), indicating the number of pilots.

The next t input lines contain the task descriptions. Each line contains three integers ( s s s, e e e, and a a a) separated by a space: 0 ≤ s < e ≤ 10000 0 ≤ s < e ≤ 10000 0s<e10000, s s 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 ) a (1 ≤ a ≤ 100) a(1a100) 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 3 3 pilots. Print, in order of descending expected score, the pilot’s number, a space, and the pilot’s expected score, rounded to 2 2 2 decimal places (i.e. a score of 42.494 would be printed as 42.49 42.49 42.49; a score of 42.495 42.495 42.495 would be printed as 42.50 42.50 42.50). Note that pilots are numbered starting at 1 1 1, not zero.

示例一

输入

3 3
0 1 5
1 2 10
2 3 15
0.0
0.0
0.2
1.0
0.0
0.0
0.0
0.75
0.0

输出

3 7.50
2 5.00
1 3.00

示例二

输入

3 4
0 3 50
3 6 50
0 6 75
0.2
0.3
0.6
0.6
0.6
0.5
0.6
0.5
0.4
0.9
0.9
0.9

输出

4 90.00
2 60.00
3 55.00

解题思路

题意解读:给出t项task的起始时间,结束时间,完成的分数,再给出p个飞行员对于每个task完成的概率,每个飞行员同一时刻只能参加一项task,只有全部完成才能得到分数,分数的期望为概率与分数的乘积。要求解的每个飞行员都得到最大分数期望时候,前三的飞行员分数。
思路分析:这道题模拟赛的时候是只剩一个小时左右才开的,题目较长,不大好读,读了好久,懂了之后发现其实这道题的思路很清晰,每个飞行员都是独立的,对于每个飞行员的分数期望类似于最优时间表问题,可以用DP来求解。然后最后再sort一下。
具体DP实现可以用一个结构体来存储task,按照时间顺序先sort一遍。

  • 如果当前时间是某个task结束的时间节点,就停下取max,状态转移方程:
    f [ i ] = m a x ( f [ i ] , f [ t a s k [ i d [ n o w ] ] . s t a r t ] + v a l [ i d [ n o w ] ] ) ; f[i]=max(f[i],f[task[id[now]].start]+val[id[now]]); f[i]=max(f[i],f[task[id[now]].start]+val[id[now]]);
  • 如果不是某个task结束的时间节点,都和前面一刻时间一样:
    f [ i ] = f [ i − 1 ] f[i]=f[i-1] f[i]=f[i1]

然后就是代码的书写了,简单的dp其实问题不大,注意,由于多个飞行员,在第一遍sort的时候不要打乱task的顺序,因此可用额外的 i d id id数组来存储遍历的顺序。

赛后补题的时候,看到也可以用线段树来维护最大期望,然后单点修改查询,也是很方便的。

Code

#include<bits/stdc++.h>
#define LL long long

using namespace std;
const int maxn=1e5+10;

struct Tasks{
    int start,end,poin,id;
}task[maxn];

double ans[maxn],val[maxn],f[maxn];
int id[maxn];
bool cmp1(int a,int b){return task[a].end<task[b].end;}
bool cmp2(int x,int y){return ans[x]>ans[y];}

int main(){
    int n,m;
    cin>>n>>m;
    for(int i=0;i<n;i++){
        cin>>task[i].start>>task[i].end>>task[i].poin;
        id[i]=i;
    }
    sort(id,id+n,cmp1); //id按照task的结束时间排序
    for(int i=0;i<m;i++){
        for(int j=0;j<n;j++){
            double x;
            cin>>x;
            val[j]=1.0*task[j].poin*x;  //每个飞行员独立,计算单项task期待值
        }
        f[0]=0;
        int cnt=0;
        for(int j=0;j<10001;j++){
            f[j]=f[j-1]; //等于前面一项
            while(cnt<n&&j==task[id[cnt]].end){ //按照结束时间从前到后,如果当前时间等于某task的结束时间
                //f[task[id[cnt]].start]+val[id[cnt]]表示完成当前task可获得的价值,取max
                f[j]=max(f[j],f[task[id[cnt]].start]+val[id[cnt]]);
                cnt++;
            }
        }
        ans[i]=f[10000];
    }
    for(int i=0;i<m;i++) id[i]=i;
    sort(id,id+m,cmp2);
    for(int i=0;i<3;i++){
        printf("%d %.2f\n",id[i]+1,ans[id[i]]);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值