寒假牛客第二场部分题解

本文解析了两道算法竞赛题目,一是寻找平面上所有三角形面积第k大的三角形面积,二是设计最少砝码数以精确测量n以内所有正整数的质量。文章详细介绍了求解方法,包括使用nth_element函数优化搜索过程,以及利用3进制原理解决砝码问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

A-处女座的签到题

平面上有n个点,问:平面上所有三角形面积第k大的三角形的面积是多少?

输入描述:

第一行T,表示样例的个数。
对于每一组样例,第一行两个整数n和k,
接下来n行,每行两个整数x,y表示点的坐标
T<=80

3<=n<=100

-109<=x,y<=109

对于每一组样例,保证任意两点不重合,且能构成的三角形的个数不小于k

输出描述:

对于每一组样例,输出第k大三角形的面积,精确到小数点后两位(四舍五入)。

示例1

输入

复制

1
4 3
1 1
0 0
0 1
0 -1

输出

复制

0.50

说明

样例中一共能构成3个三角形,面积分别为0.5,0.5,和1,面积第3大的为0.5

比赛时一开始看到这个题的通过率,被吓到了,结果到结束了也没看这个题,补题的时候看了看,感觉我当时应该能做出来...

三角形的公式之前做杭电的题时遇到过,然后就是这个找第k大的面积,排序超时后就不会了,看了看题解上用到了nth_element,然后去看了看,可能是这个题是找第k大的面积和这个函数是从小到大排序后第k个位置上的数是哪一个,两个混在一块懵逼了,在这里纠结了好长时间才真正完全搞明白,具体的可以看下我上一篇刚写的博客

这个题首先要知道给出坐标后如何求三角形的面积,在杭电第2036题中,可以得到一个结论,就是多边形的面积可以这么计算

0.5*|x1*y2-y1*x2+x2*y3-y2*x3+……+xn*y1-yn*x1|,

所以这个三角形的面积的话,取到3即可,

再就是如果找第k大的数排序的话会超时,这时就要用到一个神奇的函数nth_element,具体作用可以看上一篇博客。

然后求面积时因为数据问题要用long long ,所以就不要乘那个0.5了,但最后要记得除2

最后特判一下,如果是偶数,加个 .00

如果是奇数加个 .50

#include<bits/stdc++.h>
#define exp 1e-8
#define mian main
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ll long long
#define pb push_back
#define PI  acos(-1.0)
#define inf 0x3f3f3f3f
#define w(x) while(x--)
#define int_max 2147483647
#define lowbit(x) (x)&(-x)
#define gcd(a,b) __gcd(a,b)
#define pq(x)  priority_queue<x>
#define ull unsigned long long
#define sc(x) scanf("%d",&x)
#define scl(x) scanf("%lld",&x)
#define pl(a,n) next_permutation(a,a+n)
#define ios ios::sync_with_stdio(false)
#define met(a,x) memset((a),(x),sizeof((a)))
using namespace std;
const int N=1e7+10;
int n,k;
ll area[N];
struct node
{
    ll x;
    ll y;
}a[110];
int main()
{
    int t;
    sc(t);
    while(t--){
            scanf("%d%d",&n,&k);
        for(int i=1;i<=n;i++)
            scanf("%lld%lld",&a[i].x,&a[i].y);
            int w=1;
            for(int i=1;i<=n;i++)
                for(int j=i+1;j<=n;j++)
                for(int p=j+1;p<=n;p++){
                    ll ans=abs(a[i].x*a[j].y-a[i].y*a[j].x+a[j].x*a[p].y-a[p].x*a[j].y+a[p].x*a[i].y-a[p].y*a[i].x);
                    if(ans!=0)
                        area[w++]=ans;
                }
                nth_element(area+1,area+w-k,area+w);
                if(area[w-k]%2==0)
                    printf("%lld.00\n",area[w-k]/2);
                else printf("%lld.50\n",area[w-k]/2);
    }
}

C-处女座的砝码

题目描述

处女座热爱做物理实验,为了实验,处女座必须要精确的知道物品的质量。处女座准备自己设计一套砝码,每一个砝码都是正整数,这套砝码必须能够精确测量出n以内所有正整数的质量,处女座想要知道至少需要多少个砝码。你可以在天平的任意一边放置砝码。

输入描述:

一行,一个正整数n

1<=n<=101000

输出描述:

一个整数,表示最少的砝码数。

示例1

输入

复制

20

输出

复制

4

说明

你可以选择1,2,6,11
1=1
2=2
3=1+2
4=6-2
5=6-1
6=6
7=6+1
8=6+2
9=6+2+1
10=11-1
11=11
12=11+1
13=11+2
14=11+2+1
15=11+6-2
16=11+6-1
17=11+6
18=11+6+1
19=11+6+2
20=11+6+2+1

本来比赛时A掉的不打算写了,但是由于这个结论之前其实看过,但比赛时忘了还是写一下顺便记一下这个结论吧,并且之前也没写过java大数的题解。

比赛时只记得这个结论应该是和进制有关,但具体的忘了,本来一会就能A掉的,做了两个小时...orz

用天平要称1-Ng范围内所有的质量,最少要用到几个砝码?

一、如果可以在天平的任意一边放砝码

其实是个3进制问题,就看sigma(3^i)什么时候大于等于N,i就是最少要用到的砝码数。

二、如果只能在一边放砝码

那就是一个二进制问题,同理sigma(2^i)什么时候大于等于N,i就是最少要用到的砝码数。

import java.math.*;
import java.util.*;
public class Main
{
    public static void main(String args[]){
        Scanner cin=new Scanner(System.in);
        BigInteger n;
        BigInteger ans = new BigInteger(Integer.toString(1));
        BigInteger a = new BigInteger(Integer.toString(1));
        BigInteger b = new BigInteger(Integer.toString(3));
        while(cin.hasNext()){
            n=cin.nextBigInteger();
            for(int i=1;;i++){
                if(ans.compareTo(n)>=0){
                    System.out.println(i);
                    break;
                }
                a=a.multiply(b);
                ans=ans.add(a);
            }
        }
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值