2018, XI Samara Regional Intercollegiate Programming Contest 解题报告

2018, XI Samara Regional Intercollegiate Programming Contest

传送门


A. Restoring Numbers

题意:

给出两个数 a a a b b b 的和 s s s 和最大公因数 g g g,要你求出任意一组 a a a b b b 的解。

题解:

我们可以知道 g c d ( a , b ) = g gcd(a,b)=g gcd(a,b)=g,则我们假设 a = p ∗ g a=p*g a=pg b = q ∗ g b=q*g b=qg,那么 s = ( p + q ) ∗ g s=(p+q)*g s=(p+q)g,由此可得有解的第一个条件是 s % g = 0 s\%g=0 s%g=0

至于为什么是第一个,是因为题目描述 a a a b b b 是正数,所以上设的 p p p q q q 要大于 0 0 0,所以有解的第二个条件是 s / g > = 2 s/g>=2 s/g>=2,此时我们令 p = 1 p=1 p=1 q = s / g − 1 q=s/g-1 q=s/g1,就得到了 p p p q q q 的一组解,同时就得到了 a a a b b b 的一组解。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

int main(){
   
    int s,g;scanf("%d%d",&s,&g);
    if(s%g!=0||s/g==1) printf("-1\n");
    else printf("%d %d\n",g,s-g);
    return 0;
}

B. Minimal Area

题意:

按顺时针方向给出一个凸包上的所有点,问你以这个凸包上的点为顶点的非退化三角形的最小面积(的两倍,这个两倍应该是为了方便计算)。

题解:

考虑凸包的任意一条边作为底边,底边相同时高最小面积最小,而能做到高最小的顶点即为离底边最近的点,即从凸包上取相邻三点一定能找到最小的三角形,所以我们每次顺时针取三个点计算面积取最小值。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=200005;
struct vec{
   
    ll x,y;
}p[maxn];
vec create(vec a,vec b){
   
    return vec{
   b.x-a.x,b.y-a.y};
}
ll area(vec a,vec b){
   
    ll res=(a.x*b.y)-(b.x*a.y);
    return res<0?-res:res;
}
int main(){
   
    int n;scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%lld%lld",&p[i].x,&p[i].y);
    p[n+1]=p[1];p[n+2]=p[2];
    ll ans=0x7fffffffffffffff;
    for(int i=1;i<=n;i++){
   
        vec a=create(p[i],p[i+1]);
        vec b=create(p[i],p[i+2]);
        ans=min(ans,area(a,b));
    }
    printf("%lld\n",ans);
    return 0;
}

C. Third-Party Software

题意:

给出 n n n 条线段,问你最少选择多少个点,使得每条线段至少包含一个点,并给出这些点。

题解:

对线段进行排序,记录当前存放的节点,初始为 0 0 0。当遍历到的线段不包含当前点时,把这条线段的右端点放进答案,并更新当前点。这样首先能保证每条线段至少覆盖一个点,其次由于每次贪心选择右端点,保证选择的点尽可能少。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=200005;
struct node{
   
    int l,r;
    bool operator<(const node &t)const{
   
        if(r!=t.r) return r<t.r;
        else return l<t.l;
    }
}p[maxn];
int ans[maxn],tot;
int main(){
   
    int n;scanf("%d",&n);
    for(int i=0;i<n;i++) scanf("%d%d",&p[i].l,&p[i].r);
    sort(p,p+n);
    int now=p[0].r;
    ans[tot++]=now;
    for(int i=1;i<n;i++){
   
        if(p[i].l>now){
   
            now=p[i].r;
            ans[tot++]=now;
        }
    }
    printf("%d\n",tot);
    for(int i=0;i<tot;i++) printf("%d%c",ans[i],(i==tot-1)?'\n':' ');
    return 0;
}

D. Transfer Window

题意:

总共有 n n n 类球员,你手里有 k k k 个种类为 a 1 a_1 a1 a 2 a_2 a2,…, a k a_k a

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值