题解 | 牛客IOI周赛27-普及组

小H的小猫

https://ac.nowcoder.com/acm/contest/11234/A

A.小H的小猫

题目链接

题意

以 x 轴和 y 轴为墙,原点为墙角,小猫在墙角,给出若干个点,求能否能用篱笆绕着点将小猫围在墙角,求篱笆的最短总长

思路

  • 1.在纸上简单画图可以证明,必须要有一个点在 x 轴,一个点在 y 轴上才可以围住。
  • 2.而离原点最近的两个点可以围成最短的
  • 3.套一下两点距离公式

坑点

  • 1.画图证明,不够严谨
  • 2.精度
  • 3.卡了cin和cout的时间复杂度

代码

#include<bits/stdc++.h>
using namespace std;
struct name
{
    double x;
    double y;
    double len;
}num[1000005];
double func (double a,double b,double c,double d)//求两点距离
{
    double dis=sqrt((c-a)*(c-a)+(d-b)*(d-b));
    return dis;
}
bool cmp(name a,name b)//自定义结构体排序
{
    return a.len<b.len;
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)
    {
        scanf("%lf%lf",&num[i].x,&num[i].y);
        num[i].len=func(num[i].x,num[i].y,0,0);
    }
    sort(num,num+n,cmp);
    int res1=-1,res2=-1;
    for(int i=0;i<n;i++)
    {
        if(num[i].x==0&&res1==-1)
        {
            res1=i;
        }
        if(num[i].y==0&&res2==-1)
        {
            res2=i;
        }
        if(res1!=-1&&res2!=-1)
        {
            break;
        }
    }
    double ans=0;
    if(res1!=-1&&res2!=-1)
    {
        ans+=func(num[res1].x,num[res1].y,num[res2].x,num[res2].y);
        printf("%.10lf\n",ans);
    }else{
        printf("Poor Little H!",ans);
    }
    return 0;
}

总结

简单题,需快速写出。

小H的数列

题目链接

题意

给出一个一元二次方程,求解。

思路

  • 1.根据样例解释,可以简单的推一下结论
  • 2.可知a1=1,s2=4,a3=9,an为n的平方
  • 3.数据这么大,肯定是高精度啦

坑点

  • 1.套个高精度模板
  • 2.暴力过一半

代码

pow骗分,用多了有精度问题,慎有用

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    long long int n;
    cin>>n;
    cout<<pow(n,2);
    return 0;
}

高精度 满分 裸模板

#include <iostream>
#include <vector>

using namespace std;

vector<int> mul(vector<int> &A, vector<int> &B) {
    vector<int> C(A.size() + B.size(), 0); // 初始化为 0,且999*99最多 5 位

    for (int i = 0; i < A.size(); i++)
        for (int j = 0; j < B.size(); j++)
            C[i + j] += A[i] * B[j];

    int t = 0;
    for (int i = 0; i < C.size(); i++) { // i = C.size() - 1时 t 一定小于 10
        t += C[i];
        C[i] = t % 10;
        t /= 10;
    }

    while (C.size() > 1 && C.back() == 0) C.pop_back(); // 必须要去前导 0,因为最高位很可能是 0
    return C;
}

int main() {
    string a, b;
    cin >> a ; // a = "1222323", b = "2323423423"
    b=a;
    vector<int> A, B;
    for (int i = a.size() - 1; i >= 0; i--)
        A.push_back(a[i] - '0');
    for (int i = b.size() - 1; i >= 0; i--)
        B.push_back(b[i] - '0');

    auto C = mul(A, B);

    for (int i = C.size() - 1; i >= 0; i--)
        cout << C[i];

    return 0;
}

总结

裸模板,结论很好猜,套个模板,2分钟就结束了

小H的糖果

题目链接

题意

给定n,两种操作,操作1:n 除以 k(如果能整除),操作2:减去 1,求使 n 变为 1 的最少操作数。

思路

  • 1.题目思路转换到位,就很好做了
  • 2.先把n变为能被k整除的数(通过操作2)
  • 3.再整除k,模拟即可

坑点

  • 1.超时一时爽,一直超时一直爽,卡我endl,我裂开了,我就说为什么"\n"就过,endl就超时,导致比赛时没拿到分(原因:endl比"\n"多一个刷新缓存,影响效率),这件事告诉我们,endl少用...
  • 2.从乘法和加法,推到减法和除法,需要一定的思维能力
  • 3.学会优化,别减1就真去一个个减1

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int t;
    cin>>t;
    while(t--)
    {
        long long int k,n,ans=0;
        cin>>k>>n;
        if(k==1)
        {
            cout<<n-1<<"\n";
            continue;
        }
        while(n>=k)
        {
            ans+=n%k;//使之n能被k整除,所以需要把n变成能被k整除的数
            ans++;//整除则+1
            n=n/k;
        }
        ans+=n-1;//while循环结束的数小于等于k,则需要把其变为1
        cout<<ans<<"\n";
    }
    return 0;
}

总结

除了卡了时间以外,题目还算有趣,类似的在CF见过不少。

全部评论
没卡时间啊。。。 估计是牛客网太慢了。。。
点赞 回复
分享
发布于 2021-07-04 18:54

相关推荐

3 收藏 评论
分享
牛客网
牛客企业服务