资格赛
度度熊与邪恶大魔王
突破口在于防御值,生命值都很低,所以不必拘泥于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,于是又进了复赛。。。
复赛只会第一道模拟,卒。