比赛11 总结

来源:互联网 发布:mac 远程桌面 windows 编辑:程序博客网 时间:2024/05/22 16:43

  • T1
    • 题面
    • 题意
    • 代码
  • T2
    • 题面
    • 题意
    • 方法
    • 代码
  • T3
    • 题面
    • 题意
    • 方法
    • 代码
  • T4
    • 题面
    • 题意
    • 解析
    • 方法
    • 代码
  • T5
    • 题面
    • 题意
    • 代码

T1

题面

题意

输入a,b,c,d,输出c,d间a,b最小公倍数的数量

代码

#include<bits/stdc++.h>using namespace std;int main(){    int m,n,a,b,k,u,v;    cin>>m>>n>>a>>b;    k=m*n/__gcd(m,n);    if(a%k==0)    {        u=a/k-1;    }    else u=a/k;    v=b/k;    cout<<v-u;}

T2

题面

题意

输入n和n个点的坐标,输出这些点中任意选四个所能组成的最大面积

方法

用公式S=(x1-x2)(y3-y2)-(x2-x1) (x3-x2);
结果的正负决定了它在1,2两点的上面还是下面.

代码

#include<bits/stdc++.h>using namespace std;double x[310],y[310];int n,i,j,k;double mj(int a,int b,int c){    double a1,b1,a2,b2;    a1=x[b]-x[a],a2=x[c]-x[b];    b1=y[b]-y[a],b2=y[c]-y[b];    return a1*b2-a2*b1;}int main(){    double s=0;    cin>>n;    for(i=1;i<=n;i++)    {        scanf("%lf%lf",&x[i],&y[i]);    }    for(i=1;i<=n;i++)    {        for(j=i+1;j<=n;j++)        {            double s1=0,s2=0;            for(k=0;k<n;k++)            {                if(k!=i&&k!=j)                {                    double t=mj(i,j,k);                    if(t>0)                    {                        s1=max(s1,t/2.0);                    }                    else                    {                        s2=max(s2,-t/2.0);                    }                }            }            if(s1>0&&s2>0&&s1+s2>s)            {                s=s1+s2;            }        }    }    printf("%.6lf",s);    return 0;}

T3

题面

题意

输入n和n个在数轴上的点的坐标,输出从0开始经过所有点走过每一条路的所有方法的平均路程

方法

经过找规律发现,任选i,j这段共走过两次,0,i两点共走过一次,找规律即可

代码

#include<bits/stdc++.h>#define N 100005#define ll long longusing namespace std;ll n,num[N],sum1,sum2,sum[N],ans;ll jc(ll m){    ll i,a=1;    for(i=1;i<=m;i++)    {        a*=i;    }    return a;}ll jc2(ll m,ll n){    ll i,a=1;    for(i=m;i<=n;i++)    {        a*=i;    }    return a;}ll zh(ll m,ll n){    if(m==0) return 1;    return jc2(m-n+1,m)/jc(n);}int main(){    ll i,j,k;    cin>>n;    for(i=1;i<=n;i++)    {        cin>>num[i];        sum1+=abs(num[i]);    }    sort(num+1,num+n+1);    for(i=1;i<=n-1;i++)    {        sum[i]=num[i+1]-num[i];    }    for(i=1;i<=n-1;i++)    {        sum2+=sum[i]*zh(i,1)*zh(n-i,1);    }//  cout<<sum2;    ans+=sum1+sum2*2;    k=__gcd(n,ans);    ans/=k;    n/=k;    cout<<ans<<" "<<n;}

T4

题面

题意

输入n和n个数,冒牌排序中需要交换的两数间建一条边,则该图的最大独立子集(任意两数间都不存在一条边)是多少.

解析

题意为求最长不下降子序列,因为该序列中任意两数都不需要交换

方法

每次都将输入的数与序列末尾比较,能放在末尾就放在末尾,若小于末尾则与序列之中的数进行比较,替换掉恰好比它大的数(用*upper_bound)已达到序列中的数尽可能小的目的.

代码

#include<bits/stdc++.h>#define N 100010using namespace std;int s[N],num[N],n,k=0,p,q;int main(){    int i,j;    cin>>n;    for(i=1;i<=n;i++)    {        scanf("%d",&num[i]);    }    for(i=1;i<=n;i++)    {        if(num[i]>s[k])        {            k++;            s[k]=num[i];        }        else            *upper_bound(s+1,s+k+1,num[i])=num[i];    }    cout<<k;}

T5

题面

题意

输入n和n个数,若第i位为-1,则该位置可以放除了i以外的所有数,且这串数为1-n的一种排序,没有重复.

代码

暂无

原创粉丝点击