湖南大学第十六届程序设计竞赛(重现赛)

A题

先判断三个点是否能构成一个三角形,只有三点在同一直线上是不行的,然后用余弦定理的推论可以判断是什么类型的三角形

#include<bits/stdc++.h>
#define  maxn  1000000000 + 7
using namespace std;
typedef long long ll;
double poi[5][5];
int main()
{
    ll n;
    cin>>n;
    double x,y,z;
    while(n--)
    {
        for(int i=1;i<=3;i++)
        {
            cin>>poi[i][1]>>poi[i][2];
        }
        x=(poi[1][1]-poi[2][1])*(poi[1][1]-poi[2][1])+(poi[1][2]-poi[2][2])*(poi[1][2]-poi[2][2]);
        y=(poi[3][1]-poi[2][1])*(poi[3][1]-poi[2][1])+(poi[3][2]-poi[2][2])*(poi[3][2]-poi[2][2]);
        z=(poi[1][1]-poi[3][1])*(poi[1][1]-poi[3][1])+(poi[1][2]-poi[3][2])*(poi[1][2]-poi[3][2]);
        double t;
        if(x>z)
        {
            t=z;
            z=x;
            x=t;
        }
        if(y>z)
        {
            t=y;
            y=z;
            z=t;
        }
        if(x>y)
        {
            t=x;
            x=y;
            y=t;
        }
        double a,b,c;
        a=sqrt(x*1.00);
        b=sqrt(y*1.00);
        c=sqrt(z*1.00);
        if(a+b<=c||a+c<=b||c+b<=a)cout<<"invalid\n";
        else{
            if(x+y==z)cout<<"right\n";
            else if(x+y>z)cout<<"acute\n";
            else cout<<"obtuse\n";
        }
    }
    return 0;
}

D题

找规律,对于n个窗口,m个人,结果是1+(m-1)/n,其实也可以理解为每个人有1/n的概率站在你前面,然后共有m个人,除你之外就是(m-1)个人。

#include<bits/stdc++.h>
#define  maxn  1000000000 + 7
using namespace std;
typedef long long ll;
int main()
{
    ll m,n;
    scanf("%d%d",&n,&m);
    printf("%.8lf",1.00000000+(m-1.00000000)/n*1.00000000);
    return 0;
}

F题

签到题,高精度加法。

#include<bits/stdc++.h>
#define  maxn  1000000000 + 7
using namespace std;
typedef long long ll;
    int s[200];
int main()
{
    string a,b;
    int c;
    cin>>a>>b>>c;
    int carry=0;
    int l1,l2;
    l1=a.length();
    l2=b.length();
    int i;
    int j=50;
    s[j]=a[l1-1]-'0'+b[l1-1]-'0'+c;
    carry=s[j]/10;
    s[j]%=10;
    j--;
    for(i=l1-2;i>=0;i--)
    {
        s[j]=a[i]-'0'+b[i]-'0'+carry;
        carry=s[j]/10;
    s[j]%=10;
    j--;
    }
    if(carry)s[j]=carry;
    for(;j<=50;j++)cout<<s[j];
    return 0;
}

G题

其实输出只有三种0,1,2。两个字符串完全相同那么结果就是0,两个字符串部分相同,但是缺少前面一段或者后面一段(必须是连续的一段)那么答案是1,其他的全是2。所以我们只要分别从前往后和从后往前匹配一遍字符串即可

#include<bits/stdc++.h>
#define  maxn  1000000000 + 7
using namespace std;
typedef long long ll;
string s,t;
int main()
{
    cin>>s>>t;
    ll l1,l2;
    l1=s.length();
    l2=t.length();
    ll i,j;
    i=j=0;
    ll sum=0;
    while(i<l1&&j<l1)
    {
        if(s[i]==t[j])
        {
            i++;
            j++;
            sum++;
        }
        else break;
    }
    i=l1-1;
    j=l2-1;
    while(i>=0&&j>=0)
    {

        if(s[i]==t[j])
        {
            i--;
            j--;
            sum++;
        }
        else break;
    }
    if(sum==2*l1&&l1==l2)cout<<0<<'\n';
    else if(sum==l1||l2==sum)cout<<1<<'\n';
    else cout<<2<<'\n';
    return 0;
}

I题

题目只给了我们两个小球,因此我们只有两次失败的机会,当我们尝试失败了,我们只能从保证扔下去不会碎的楼层开始,从下往上尝试,假设我们最差的情况下最少需要扔x次,那么假如第一次失败了,我们就要从下往上挨个楼层尝试,那么就是第一次在x楼扔碎了第一颗球,此时拿第二颗球从下往上尝试刚好是x次,以此类推,如果成功了,我们第二次就要从2x-1层往下扔,为了保证不管是成功还是失败,结果都是要x次,以此类推,最高的楼层就是(x+1)x/2,当(x+1)*x/2>=n时,满足不等式的最小正整数x即为本题答案,进一步化简可以得到O(1)的表达式ans =ceil((sqrt(1 + 8 * n) - 1) / 2);

#include<bits/stdc++.h>
#define  maxn  1000000000 + 7
using namespace std;
typedef long long ll;
ll a[1000000];
int main()
{
    ll t,n;
    cin>>t;
    while(t--)
    {
        cin>>n;
        long long ans =ceil((sqrt(1 + 8 * n) - 1) / 2);
        cout<<ans<<endl;
    }
    return 0;
}