ICPC North Central NA Contest 2018(部分题解)

Lipschitz Constant

题目链接

题目大意就是给出n对x和f(x),然后任意两对都要满足|f(x1)-f(x2)|<=L*|x1-x2|,求其中最大的L,说白了就是求所有组合中最大的|f(x1)-f(x2)|/|x1-x2|。然后首先直接暴力所有组合是会超时的,因为其中有完全没必要遍历到的组合。转换一下思路,把每个点转换到坐标系上面,其实求的就是两点的斜率的绝对值的最大值,然后我们可以很清楚的发现最大斜率一定出现在相邻点中。不知为何的请继续看:这里假设两个点Xn,Xm(如下图),如果它们两点中有点的话,无非就如以下Xk1,2,3三种情况,很容易就可以看出出只要中间还有点,那么中间的点的与Xn或Xm的某个组合的斜率一定会大于等于Xn和Xm的斜率,所以最大的斜率肯定在相邻点中出现,所以只要把点按x排序(本题中每个x都不同),最后算出最大的相邻斜率就可以了。
在这里插入图片描述

#include<iostream>
#include<cstdio>
#include<cmath>
#include<algorithm>
using namespace std;
struct k
{
    double x,fx;
}dian[200010];
bool cmp(k a,k b)
{
    if(a.x!=b.x)
        return a.x<b.x;
    return a.fx<b.fx;
}
int main()
{
    int n;
    double ans=-1;
    cin>>n;
    for(int i=0;i<n;++i)
        scanf("%lf%lf",&dian[i].x,&dian[i].fx);
    sort(dian,dian+n,cmp);
    for(int i=1;i<n;++i)
    {
        double l=fabs(dian[i].fx-dian[i-1].fx)/fabs(dian[i].x-dian[i-1].x);
        if(l>ans)
            ans=l;
    }
    printf("%lf",ans);
}

Rational Ratio

题目链接
题目大意就是给一个小数X,然后再给一个数字u,表示从X右边开始往左数的u位数字是这个小数的无限循环的几个数字,然后求出这个无限循环小数由哪两个整数相除而来,最后答案要给最简比。比如输入123.456 2,那么就代表这个小数是123.456565656……,这个数由1除7得来,所以答案输出1/7。那么这里只要用一个小技巧,或者说公式吧,就可以解决这个问题。假设一个小数X=abcd.efghij,然后小数点后面有n位数字,这n位数字中不属于循环体的数字有k位,则有下图关系(YZ分别是X乘以10k,和10n后的整数部分的值)。最后答案记得换成最简整数比,
在这里插入图片描述
要实现这个过程应该方法不少,但是一开始想快一点写出来用了atof()函数,但是没有过,atof可能到达不了题目那个精度。后面考虑只用整数来写,反正小数部分的循环体最后会被约掉,这里的数字的范围好像就是long long,用atoll就可以过了。

#include<bits/stdc++.h>
using namespace std;
long long gcd(long long a,long long b)
{
    return b==0?a:gcd(b,a%b);
}
int main()
{
    char x[100];
    cin>>x;
    char y[100];
    strcpy(y,x);
    long long n,len=strlen(x),fei,i,ans1,ans2,con,j,a,b;
    cin>>n;
    for(i=0;i<len;++i)
    {
        if(x[i]=='.')
            break;
    }
    j=i;
    fei=(len-i-1)-n;
    for(con=0;con<fei;++con)
        x[j+con]=x[j+con+1];
    x[j+con]=0;
    a=atoll(x);
    j=i;
    for(con=0;con<len-i-1;++con)
        y[j+con]=y[j+con+1];
    y[j+con]=0;
    b=atoll(y);
    fei=pow(10,(len-i-1)-n);
    n=pow(10,len-i-1);
    ans1=n-fei,ans2=b-a;
    long long g=gcd(ans1,ans2);
    cout<<ans2/g<<'/'<<ans1/g;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值