AtCoder Beginner Contest 153 A-F题解

A - Serval vs Monster

答案为h/a向上取整

#include
#define ll long long
using namespace std;
#define maxn 200000+66
int main()
{
    int h,a;
    while(cin>>h>>a)
    {
        cout<

B - Common Raccoon vs Monster

直接比较和与h的值即可

#include
#define ll long long
using namespace std;
#define maxn 200000+66
int main()
{
    int h,a;
    while(cin>>h>>a)
    {
        int s=0;
        for(int i=1;i<=a;i++)
        {
            int x;
            cin>>x;
            s+=x;
        }
        if(s>=h)
        {
            cout<<"Yes"<

C - Fennec vs Monster

排序,然后累加前h-k项即可

#include
#define ll long long
using namespace std;
#define maxn 200000+66
int a[maxn];
bool cmp(int a,int b)
{
    return a>h>>k)
    {
        for(int i=1;i<=h;i++)
        {
            cin>>a[i];
        }
        sort(a+1,a+h+1);
        ll s=0;
        for(int i=1;i<=h-k;i++)
        {
            s+=a[i];
        }
        cout<

D - Caracal vs Monster

一血量为X的怪兽,若X<=1,则被攻击后消失,否则变为两个血量为X/2向下取整的怪兽,问最小攻击多少次使得怪兽全部消灭。

一看就是有规律,利用队列打表,打表程序如下:

#include
#define ll long long
using namespace std;
#define maxn 200000+66
int a[maxn];
bool cmp(int a,int b)
{
    return aq;
int main()
{
    ll h,k;
    for(int h=1;h<=200;h++)
    {
        while(q.size())q.pop();
        q.push(h);
        ll ans=0;
        while(q.size())
        {
            int x=q.front();
            q.pop();
            ans++;
            //cout<1)
            {
                q.push(x/2);
                q.push(x/2);
            }
        }
        cout<

发现有个规律:  a[i]=2*a[i-1]+1   那么只要锁定给出的是第几项就好了。

就是让它不断/2,看能除几次。

#include
#define ll long long
using namespace std;
#define maxn 200000+66
ll a[maxn];
int main()
{
    ll h,k;
    a[0]=1;
    for(int i=1;i<=100000;i++)
    {
        a[i]=2*a[i-1]+1;
    }
    while(cin>>h)
    {
        ll ans=0;
        int cnt=0;
        while(h>0)
        {
            h/=2;
            cnt++;
        }

        cout<

E - Crested Ibis vs Monster

怪兽有H血量,你有N种技能,每种技能有A攻击力和B体力消耗,问能消灭怪兽用的最小体力消耗。

完全背包问题,dpi即为装入i攻击力的最小体力消耗,从m开始枚举装入i攻击力所得体力消耗最小值,取最小的。

#include 
using namespace std;
const int maxn = 1000+20;
const int INF = 0x3f3f3f3f;
int p[maxn], v[maxn];
int dp[20000+50];
int main()
{
    int n, m;
    while(scanf("%d %d", &m, &n)!=EOF) {
        for(int i = 1; i <= n; i++) {
            scanf("%d %d", &v[i], &p[i]);
        }
        memset(dp, INF, sizeof(dp));
        dp[0] = 0;
        for(int i = 1; i <= n; i++) {
            for(int j = v[i]; j <= 20000; j++) {
                dp[j] = min(dp[j], dp[j-v[i]] + p[i]);
            }
        }

        int maxx = dp[m];
        for(int i=m;i<=20000;i++)
        {
            if(dp[i]

F - Silver Fox vs Monster

给出怪物的位置和生命力,还有伤害范围d,在i处放炸弹伤害区域为i-d--i+d,每次伤害a点生命值。问至少炸几次会消灭所有怪物。

首先贪心原则是:在i处的怪物,最优是放在i+d处,这样可以伤害i+2*d范围内的怪物。

然后会有一个二重循环朴素做法,会超时,利用尺取+差分来优化。

c数组代表已经在某点炸了几次。

首先得到j,即利用此贪心原则所能伤害到的最大位置+1,然后用cj-=need。

c[i+1]+=c[i]。答案累加need。

#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define ll long long
using namespace std;
const int maxn=200000+66;
struct monster
{
    ll x,h;
}mon[maxn];
bool cmp(monster a,monster b)
{
    return a.x>n>>d>>a;
    rep(i,1,n)
    {
        cin>>mon[i].x>>mon[i].h;
    }
    sort(mon+1,mon+n+1,cmp);
    ll ans=0;
    //尺取法,贪心原则:第i点要炸时在i+d点放炸弹
    //c数组代表已经炸了多少次
    for(int i=1,j=1;i<=n;i++)
    {
        while(j<=n&&mon[j].x<=mon[i].x+2*d)
            j++;//找到不能炸到的
        ll need=max((mon[i].h-c[i]*a+a-1)/a,0ll);
        c[i]+=need;
        c[j]-=need;
        c[i+1]+=c[i];
        ans+=need;
    }
    cout<

 

你可能感兴趣的:(CF+AtCoder题录)