Codeforces 280 DIV2

A题:告诉你一种搭房子的姿势第一层用1个木块,第二层用1+2个木块,第n层用1+2..+n个木块,现在给你M个木块,问最多能够搭出多少层的房子。

思路:数据范围巨小,直接处理搭1-N层房子各要多少个木块即可,然后判断一下当前木块数是否大于等于共搭i层时所需要的木块同时小于等于搭i+1层的木块,小于等于的地方记得特判一下是否刚好等于要搭i+1层房子的木块和,分类输出即可。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int sum[205];
int a[205];
void init()
{
    for(int i=1;i<=200;i++)
    {
        a[i]=((i+1)*i)/2;
    }
    sum[1]=1;
    for(int i=2;i<=200;i++)
    {
        sum[i]=sum[i-1]+a[i];
    }

}

int main()
{
    init();
    int n;
    cin>>n;
    for(int i=1;i<=200;i++)
    {
        if(sum[i]<=n&&n<=sum[i+1])
        {
            if(n==sum[i+1])
            {
                cout<<i+1<<endl;
            return 0;
            }
            else
            {
                cout<<i<<endl;
                return 0;
            }

        }
    }
    return 0;
}

B题:给你N个位置,问至少需要光照半径为多少的灯笼,然后统一在两两间放置灯笼可以使得全部的地方被照亮。

思路:SORT一下求两两间的距离/2的最大值,然后跟两个端点的情况特判一下最大值即可。左端点的半径就为左端点所在的那个位置,右端点所需的半径为L-最后一个点的位置

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
double  a[1005];
int main()
{
    int n,l;
    cin>>n>>l;

    for(int i=0;i<n;i++)
    {
        cin>>a[i];
    }
    sort(a,a+n);
    double ans=max(a[0],l-a[n-1]);
    for(int i=1;i<n;i++)
    {
        ans=max(ans,(a[i]-a[i-1])/2);
    }
    printf("%.10lf\n",ans);
    return 0;
}

C题:给你N门课程,和买分最高可以买到的上限分数为r分,以及给你通过所有课程的平均分AVG,接下来给你这个人N门课的成绩和把每门课提高1分所要花的钱,问最少需要花多少钱可以让这个人过。。

思路:按照花钱的升序排序啊,裸贪心,不过注意一下是否直接平均分就达到要求的情况,这样就不用花RMB了,然后贪心的过程要注意不能一门课无限加,要用R-该门课已经有的成绩去和总共需要补的分去比较,如果更小就把差值补上,更新还需要的分数,否则直接加上还需要的分数*该门课的RMB就好了。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;

struct node{

long long a;
long long  b;

}c[100005];

bool cmp(node aa,node bb)
{
    return aa.b<bb.b;
}

int main()
{

    long long  n,r,avg;
    cin>>n>>r>>avg;
    long long sum=avg*n;
    for(int i=0;i<n;i++)
    {
        cin>>c[i].a>>c[i].b;
        sum-=c[i].a;
    }
   // cout<<sum<<endl;
    sort(c,c+n,cmp);
    long long res=0;
    if(sum<=0)
    {
        cout<<0<<endl;
    }
    else
    {
        for(int i=0;i<n;i++)
        {
            long long cha=r-c[i].a;
            if(cha<sum)
            {
                sum-=cha;
                res+=cha*c[i].b;
            }
            else
            {
                res+=sum*c[i].b;
                break;
            }
    }
    cout<<res<<endl;
    }

    return 0;

}

D题:蛮有意思的一道题,两个人同时打N只小怪兽,第一个人每1/X秒对所有还没挂的怪兽去血一滴,同理第二个人每1/Y秒对还没挂的怪兽去血一滴,然后问每只怪兽是谁干掉的,当然这只怪兽也有可能是在同一时刻两个人都发动了进攻一起干掉的。

思路:看到这题,首先看数据,尼玛那么大,肯定有循环,发现循环节是(X+Y)/GCD(X,Y),不过这个只是可以减小输入的N个怪兽的血的范围。

接着其实可以自己模拟一下去血的过程:

4 3 2
1
2
3
4
比如这组数据 第一个人每1/3秒对怪兽攻击一次,第二个人每1/2秒攻击一次,那么我们只要模拟一个时间段内,每一时刻是第一个人攻击了怪兽还是第二个人攻击了怪兽还是一起攻击了怪兽,然后这个是分数比较EGGS PAIN 所以通分一下就好看了,第一个时刻1*3>1*2(等价于第1/3秒时的情况)所以是第一个人打了怪兽,所以第二个人的时刻++,到下一时刻 1*3<2*2(1/2秒的情况)所以是第二个人打了怪兽,接着第一个人的时刻++,然后2*3>2*2所以又是第一个人攻击怪兽,此时第二个人时刻++,最后发现2*3=3*2了说明该时刻两个人同时攻击了怪兽,双方时刻都加,在这个模拟的过程中复杂度是MAX(O(N,M))然后通过这个模拟也可以求得这个周期大小,于是查询的时候都是O(1)了,这道题太考YY能力了,好恶心。。。。

#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int ans[2000010];
int main()
{
    long long n,x,y;
    cin>>n>>x>>y;
    long long  i,j;
    int sum=0;
    for(i=1,j=1;i<=y&&j<=x;)
    {
        if(i*x<j*y)
        {
            ans[++sum]=2;
            i++;
            continue;
        }
        if(i*x>j*y)
        {
            ans[++sum]=1;
            j++;
            continue;
        }
        if(i*x==y*j)
        {
            ans[++sum]=0;
            ans[++sum]=0;
            i++;
            j++;
            continue;
        }
    }
   // cout<<sum<<endl;
    for(i=0;i<n;i++)
    {
        long long a;
        cin>>a;
        a%=sum;
        if(ans[a]==1)
        {
            cout<<"Vanya"<<endl;
        }
        else if(ans[a]==2)
        {
            cout<<"Vova"<<endl;
        }
        else
        {
            cout<<"Both"<<endl;
        }
    }
    return 0;
}
E:说的是一个大小为N*N的果园中在M个地方种有苹果树,然后主人公可以随意固定一个起点(X,Y),然后每次走到(X+DX)%N,(Y+DY)%N的道路,问从哪个地方走可以经过的苹果树最多,并且给定的数据满足:GCD(N,DX)=GCD(N,DY)=1

思路:显然不知道怎么做的情况就画画啊。。。发现N*N个格子,被分成了N组,然后每个组有N个点是完全等价的(每个组里面任意取一个点能到达的地方都相同),走N步又回到了起点,然后就不知道怎么搞了。。。看题解,题解上说(0,0)、(0,1)、...(0、N-1)恰好是N个不同的等价的点,而且所形成的路线由于那个GCD互素的缘故两两不相交。于是可以先预处理出从(0,0)出发的点走N步给每步的的坐标建立一个映射保存。然后我们从输入的苹果树去找对应的是从哪个(0,Y)点过来的统计一下谁最大就OK了从(0,0)走K步到(0+KDX)%N (0+KDY)%N的地方记为X[K],Y[K],然后从(0,Y)走N步最后到的就是X[k],Y+Y[k],所以可以反推回去那个Y是什么鬼就出来了。

#include<cstdio>
#include<cstring>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;

int cnt[1000005];
int d[1000005];

int main()
{
    int n,m,dx,dy;
    cin>>n>>m>>dx>>dy;
    int x=0;
    int y=0;
    for(int i=0;i<n;i++)
    {
        d[x]=y;
        x=(x+dx)%n;
        y=(y+dy)%n;
    }//0.0出发走N步所建立的一个X->Y的映射

    for(int i=0;i<m;i++)
    {
        int x1,y1;
        cin>>x1>>y1;
        cnt[(y1-d[x1]+n)%n]++;
    }//根据当前映射判断是从哪个点走过来的
    int ans=-1;
    int pos=0;
    for(int i=0;i<n;i++)
    {
        if(cnt[i]>ans)
        {
            ans=cnt[i];
            pos=i;
        }
    }
    cout<<0<<" "<<pos<<endl;
    return 0;
}

因为这场比赛所有的题目过题数都很多- -所以才尝试着去每道题都看了,果然要自己做AK还是不可能总得借助外力才能干掉,果然弱,SIGH。。。。。



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值