2017百度之星作死记

资格赛

度度熊与邪恶大魔王

突破口在于防御值,生命值都很低,所以不必拘泥于n
可以预处理出对于防御值i,生命值j的怪兽的最小花费,做一个完全背包
然后对每个询问直接输出

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int n,m,can;
int a[100005],b[100005];
int c[1005],p[1005],f[15][1005];
long long ans;
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF) 
    {
        ans=0;can=1;
        for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]);
        for(int i=1;i<=m;i++) scanf("%d%d",&c[i],&p[i]);
        for(int i=0;i<=10;i++) 
        for(int j=1;j<=1000;j++) f[i][j]=1e9;
        for(int i=1;i<=m;i++) 
        {
            for(int j=0;j<=10;j++)  //枚举防御
            for(int k=1;k<=1000;k++) //生命值 
            if(p[i]-j>0) f[j][k]=min(f[j][k],f[j][max(0,k-(p[i]-j))]+c[i]);
        }
        for(int i=1;i<=n;i++) 
        if(f[b[i]][a[i]]==1e9) can=0; else ans=ans+f[b[i]][a[i]];
        if(can) printf("%I64d\n",ans); else printf("-1\n");
    }
    return 0;
}

初赛A

今夕何夕

码农题,想明白就行

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
int cas;
char a[20];
int b[20],p[20];
int year,month,day,s,id,lwq,now;
int run(int x)
{
    if(x%100==0) 
    {
        if(x%400==0) return 1; else return 0;
    }
    if(x%4==0) return 1; else return 0;
}
int main()
{
    b[1]=31;b[2]=28;b[3]=31;
    b[4]=30;b[5]=31;b[6]=30;
    b[7]=31;b[8]=31;b[9]=30;
    b[10]=31;b[11]=30;b[12]=31;
    for(int i=1;i<=12;i++) p[i]=p[i-1]+b[i];
    cin>>cas;
    while(cas--) 
    {
        scanf("%s",a+1);
        year=(a[1]-48)*1000+(a[2]-48)*100+(a[3]-48)*10+a[4]-48;
        month=(a[6]-48)*10+(a[7]-48);
        day=(a[9]-48)*10+(a[10]-48);
        if(month==2&&day==29) lwq=1; else lwq=0;
        s=0;
        now=365+run(year);
        if(month>2) id=p[month-1]+run(year); else id=p[month-1];
        id=id+day; //是每年的第几天 
        s=(s+now-id)%7;
        while(1) 
        {
            year++;
            now=365+run(year);
            if(month>2) id=p[month-1]+run(year); else id=p[month-1];
            if(lwq==1) id=id+28+run(year); else id=id+day;
            s=(s+id)%7;
            if(s==0) 
            {
                if(lwq==1) 
                {
                    if(run(year)==1) break;
                }
                else break;
            }
            s=(s+now-id)%7;
        }
        printf("%d\n",year);
    }        
    return 0;
}

度度熊的01世界

先找1联通块,如果1联通块只有1个,那么0的联通块只要不碰到边界就肯定被1完全包围,dfs即可

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
int n,m,s,zero,ans;
char a[105][105];
int p[105][105];
void dfs(int x,int y)
{
    p[x][y]=1;
    if(x+1<=n&&p[x+1][y]==0&&a[x+1][y]=='1') dfs(x+1,y);
    if(x-1>0&&p[x-1][y]==0&&a[x-1][y]=='1') dfs(x-1,y);
    if(y+1<=m&&p[x][y+1]==0&&a[x][y+1]=='1') dfs(x,y+1);
    if(y-1>0&&p[x][y-1]==0&&a[x][y-1]=='1') dfs(x,y-1);
}
int lwq(int x,int y)
{
    int ty=0;
    p[x][y]=1;
    if(x==1||x==n||y==1||y==m) ty=1;
    if(x+1<=n&&p[x+1][y]==0&&a[x+1][y]=='0') ty=ty|lwq(x+1,y);
    if(x-1>0&&p[x-1][y]==0&&a[x-1][y]=='0') ty=ty|lwq(x-1,y);
    if(y+1<=m&&p[x][y+1]==0&&a[x][y+1]=='0') ty=ty|lwq(x,y+1);
    if(y-1>0&&p[x][y-1]==0&&a[x][y-1]=='0') ty=ty|lwq(x,y-1);
    return ty;
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF) 
    {
        s=zero=0;
        ans=-1;
        for(int i=1;i<=n;i++) scanf("%s",a[i]+1);
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) p[i][j]=0;
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
        if(p[i][j]==0&&a[i][j]=='1') 
        {
            s++;
            if(s>1) ans=-1;
            dfs(i,j);
        }
        for(int i=1;i<=n;i++) 
        for(int j=1;j<=m;j++) 
        if(p[i][j]==0&&a[i][j]=='0') 
        {
            if(lwq(i,j)==0) zero++;
            if(zero>1) ans=-1;
        }
        if(s==1&&zero==1) ans=0;
        if(s==1&&zero==0) ans=1;
        printf("%d\n",ans);
    }
    return 0;
}

初赛B

Chess
组合数

#include<cstdio>
#include<iostream>
using namespace std;
const int mod=1e9+7;
int n,m,t;
int f[1005][1005];  
int main()
{
    for(int i=1;i<=1000;i++) f[i][0]=1;
    f[1][1]=1;
    for(int i=2;i<=1000;i++) 
    for(int j=1;j<=i;j++) f[i][j]=(f[i-1][j]+f[i-1][j-1])%mod;
    cin>>t;
    while(t--) 
    {
        scanf("%d%d",&n,&m);
        if(n<m) swap(n,m);
        printf("%d\n",f[n][m]);
    }
    return 0;
}

小小粉丝度度熊

先合并区间,然后二分答案,有许多情况需要判断,十分难写。

#include<cstdio>
#include<algorithm>
#include<iostream>
#define ll long long
using namespace std;
int n,m,len,now;
ll far;
struct ty
{
    ll l,r;
}a[100005];
ll b[100005],c[100005],s[100005];
bool cmp(ty x,ty y)
{
    if(x.l!=y.l) return x.l<y.l;
    return x.r<y.r;
}
int erfen(ll l,ll r)
{
    if(l>r) return l;
    ll mid=(l+r)/2,can=0,cost,id;
    for(int i=1;i<=len;i++) 
    {
        int L=i,R=len,Mid;
        while(L<=R) 
        {
            Mid=(L+R)/2;
            if(c[Mid]-b[i]+1<mid) L=Mid+1; else R=Mid-1;
        }
        id=L;
        if(id==len+1) 
        {
            cost=s[len]-s[i]+(mid-(c[len]-b[i]))-1;
            if(cost<=m) can=1;
        }
        else 
        {
            if(c[id]-b[i]+1>mid) 
            {
                if(b[id]-b[i]<=mid) cost=s[id]-s[i]; else cost=s[id-1]-s[i]+(mid-(c[id-1]-b[i]))-1;
                if(cost<=m) can=1;
            }
            if(c[id]-b[i]+1==mid) 
            {
                 if(s[id]-s[i]<=m) can=1;
            }
        }
    }
    if(can==1) return erfen(mid+1,r); else return erfen(l,mid-1);
}
int main()
{
    while(scanf("%d%d",&n,&m)!=EOF) 
    {
        len=0; 
        for(int i=1;i<=n;i++) scanf("%I64d%I64d",&a[i].l,&a[i].r);
        sort(a+1,a+n+1,cmp);
        far=a[1].r;now=1;
        for(int i=2;i<=n;i++) 
        if(a[i].l<=far) far=max(far,a[i].r);
        else 
        {
            len++;
            b[len]=a[now].l;
            c[len]=far;
            now=i;
            far=a[i].r;
        }
        len++;
        b[len]=a[now].l;
        c[len]=far;
        for(int i=2;i<=len;i++) s[i]=s[i-1]+(b[i]-c[i-1])-1;
        printf("%I64d\n",erfen(1,2000000000)-1);
    }
    return 0;
}

后记

本来以为复赛肯定是进不了了,结果主办方说初赛A评测情况不好,所以为了补偿,取每场前800,于是又进了复赛。。。
复赛只会第一道模拟,卒。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值