比赛4 总结

T1

题面

题意

球场上有n名观众,从1到N号,他们在0时开始观看比赛。
在1时,第一个观众起立。
在2时,第二个观众起立。

在k时,第k个观众起立。

在k + 1时,第一个观众坐下。
在k + 2时,第二个观众坐下。

在n时,第n个观众起立和第(n- k)个观众坐下。

输入n,k,t,输出站着的观众数

代码

#include<bits/stdc++.h>
using namespace std;

int main()
{
    int n,k,t,i;
    cin>>n>>k>>t;
    if(t<=k)
    {
        cout<<t;
        return 0;
    }
    if(t>k&&t<=n)
    {
        cout<<k;
        return 0;
    }
    if(t>n&&t<=n+k)
    {
        cout<<n+k-t;
        return 0;
    }
    if(t>n+k)
    {
        cout<<0;
        return 0;
    }
}

方法

分四类进行讨论:人数增加,再不变(起立与坐下平衡)再减少,最后不变(为0).

T2

题面

题意

输入三个点A,B,C的坐标.
问是否能找到某一个点和某一个角度,我们若将页面围绕这个点旋转这个角度,能使A的新位置和B的旧位置一样,B的新位置和C的旧位置一样。

代码

#include<bits/stdc++.h>
using namespace std;
int main()
{
    long long ax,ay,bx,by,cx,cy;
    double jl1,jl2;
    cin>>ax>>ay>>bx>>by>>cx>>cy;
    if((ax-bx)*(by-cy)==(ay-by)*(bx-cx))//判断斜率是否相同以判断是否三点共线
    {
        cout<<"No";
        return 0;
    }
    //若绕AB中垂线上一点转,必能找到一个角度使新A与B重合
    //若三点不共线,则AB与BC的中垂线必有交点
    jl1=sqrt((ax-bx)*(ax-bx)+(ay-by)*(ay-by));
    jl2=sqrt((cx-bx)*(cx-bx)+(cy-by)*(cy-by));
    if(jl1==jl2)
    {
        cout<<"Yes";
        return 0;
    }//判断距离是否相等来判断能否完成
    cout<<"No";
}

T3

题面

题意

输入n,再输入n个五维空间中点的坐标.若以一个点为顶点,将另外任意两点与它相连,构成的夹角均大于等于90度,则为好点
输出好点数,以下几行每行一个整数表示好点序号

代码

#include<bits/stdc++.h>
using namespace std;
/*
6
0 0 0 0 0
1 0 0 0 0
0 1 0 0 0
0 0 1 0 0
0 0 0 1 0
0 0 0 0 1
*/
/*
1
1
*/
//样例
const long long N=1010;
long long an[N],ans=0,a[N],b[N],c[N],d[N],e[N],n,dc[N];

int js(long long p,long long q)
{
    long long sum,ji1,ji2,ji3,ji4,ji5;
    ji1=a[p]-a[q];
    ji2=b[p]-b[q];
    ji3=c[p]-c[q];
    ji4=d[p]-d[q];
    ji5=e[p]-e[q];
    sum=ji1*ji1+ji2*ji2+ji3*ji3+ji4*ji4+ji5*ji5;
    return sum;
}
//勾股定理(扩展版),计算两点间距离的平方
int jy(long long j,long long b1,long long b2)
{
    if(js(j,b1)+js(j,b2)<=js(b1,b2))
    return 0;
    else return 1;
}
//若角的两夹边的平方和小于等于对边的平方则该角(小于180)为直角或钝角
int main()
{
    long long i,j,k,pd,pd2;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a[i]>>b[i]>>c[i]>>d[i]>>e[i];
    }
    if(n<3)
    {
        cout<<n<<endl;
        for(i=1;i<=n;i++)
        cout<<i<<endl;
        return 0;
    }

    for(i=1;i<=n;i++)//i表示角的顶点
    {
        pd=0;
        for(j=1;j<=n;j++)
        {
            if(j!=i)
            {
                pd2=0;
                for(k=j+1;k<=n;k++)//列举端点k,j来判断是否满足所有
                {
                    if(k!=i)
                    {
                        if(jy(i,j,k)==1)
                        {
                            pd2=1;
                            break;
                        }
                    }
                }
                if(pd2==1)
                {
                    pd=1;
                    break;
                }
            }
        }
        if(pd==0)
        {
            ans++;
            an[ans]=i;
        }
    }

    cout<<ans<<endl;
    for(i=1;i<=ans;i++)
    cout<<an[i]<<endl;
}

方法

暴力穷举每一个顶点,并穷举其余两顶点,用勾股定理来判断

T4

题面

题意

有N个骰子 D1,D2….DN。第i个骰子上的数字是从1到i。掷骰子(每一个骰子掷一次)的数字总和为A.
不知道每一个骰子显示什么号码,但知道每个骰子的面数 D1,D2 …..DN,故知道每个骰子有R个数不能显示。
例如,有两个六面骰子的总和是11,那么两个骰子不能显示小于五的值(否则,剩下的骰子必须至少为七,这样是不可能的)。
输入
第一行包含两个整数n, A,(1 ≤ N ≤ 2·105, N ≤ A ≤ S)n为骰子的数量,A为显示点数之和S=D1+D2+…..DN。
第二行包含N个整数 D1,D2……DN(1 ≤ Di ≤ 106.
输出
打印n个整数 B1,B2, …,Bn,其中BI是第i个骰子不能显示的数字个数

代码

#include<bits/stdc++.h>
using namespace std;

long long n,sum,s,a[200001],ans[200001];

int main()
{
    long long min,max,i;
    cin>>n>>sum;
    for(i=1;i<=n;i++)
    {
        cin>>a[i];
        s+=a[i];//记录面数之和方便后续计算
    }

    for(i=1;i<=n;i++)
    {
        max=sum-n+1;
        min=sum-(s-a[i]);//该骰子能显示的最大值与最小值
//      cout<<min<<" "<<max<<" ";
        if(1<min)
        {
            ans[i]=ans[i]+min-1;
        }
        if(a[i]>max)
        {
            ans[i]=ans[i]+a[i]-max;
        }
//      cout<<ans[i]<<" ";
    }

    for(i=1;i<=n;i++)
    cout<<ans[i]<<" ";
}

T5

题面

题意

输入一个整数序列,进行一系列操作使它的最大值恰好为最小公倍数.
操作:可以将序列中任何一个数变为小于等于它的数.
输出操作总数对1000000007取模的结果

方法

通过前缀和来记录一个区间内数的个数,详见代码.
求出最大值,并枚举
每乘一次就对1000000007取一次模

代码

#include<bits/stdc++.h>
#define N 100010
#define ll long long
#define M 1000000007
using namespace std;

ll n,a,cnt[N],sum[N],mx,an,ans;

ll pow(ll u,ll v)
{
    ll i,z=1;
    while(v!=0)
    {
        if(v&1)//如果转化为2进制后末位为1
        z=z*u%M;//就乘u
        u=u*u%M;
        v=(v >> 1);//v=v/2,位运算较快
    }
    return z;
}
//这样写指数函数更快
ll fj(ll u)//该函数将u的因子存在了cnt中,且长度为j
{
    ll i,j=0,v;
    v=(ll)sqrt(u);
    for(i=1;i<=v;i++)//枚举到根号u,若i能整除,则u/i也能
    {
        if(u%i==0)
        {
            j++;
            cnt[j]=i;
            if(i*i!=u)
            {
                j++;
                cnt[j]=u/i;
            }
        }
    }
    return j;
}

void js(ll z)
{
    ll i,j,len,gs,k;
    an=1;
    len=fj(z);
    sort(cnt+1,cnt+len+1);
    for(i=1;i<len;i++)
    {
        an=(an*pow(i,sum[cnt[i+1]-1]-sum[cnt[i]-1]))%M;
        //在第i个因子到第i+1个因子间,每个因子都有i个选择
    }
    gs=n-sum[cnt[len]-1];
    k=(pow(len,gs)+M-pow(len-1,gs))%M;//最大值特判,因为必须有数为最大值
    an=(an*k)%M;
    ans=(ans+an)%M;
}

int main()
{
    ll i,j,p=0;
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>a;
        mx=max(mx,a);
        sum[a]++;
    }

    for(i=1;i<N;i++)
    {
        sum[i]+=sum[i-1];//用前缀和维护,方便计算
    }

    for(i=1;i<=mx;i++)//枚举最大值
    {
        js(i);
    }
    cout<<ans;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值