比赛地址:http://acm.hust.edu.cn:8080/judge/contest/view.action?cid=17732#overview
第一题:给你一个数,看能不能分割成两个偶数
分析:水到不贴代码了。。。
第二题:给你一个数,能不能分割成n份,每份有上下限
分析:直接贪心搞定。。。
第三题:要求写一个注册系统,如果一个名字没出现过,就返回OK,如果出现过,就自动在末尾加数字,从1开始,直到这个新名字没出现过,并返回给用户,同时保存在数据库里。。。
分析:按这个题面描述,它是一道难题,不过由于题目是错的,所以只需要判断一个名字出现几次,在后面多输出那个次数就行。。。
为什么说题目错了呢?下面这组数据告诉你:
3
t1
t
t
这样,估计你们的程序都会输出
OK
OK
t1
呵呵,不解释了,反正因此我把他当难题,然后被虐成渣了
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int mm=1000007;
struct hashtable
{
int h[mm],p[mm],size;
int d[111111];
char s[111111][44];
int hash(char *a)
{
int id=0;
while(*a)id=id*131+(*a++);
return (id&0x7FFFFFFF)%mm;
}
int insert(char *a)
{
int i,id=hash(a);
for(i=h[id];i>=0;i=p[i])
if(!strcmp(a,s[i]))return i;
d[size]=1;
strcpy(s[size],a);
p[size]=h[id],h[id]=size++;
return -1;
}
void clear()
{
size=0;
memset(h,-1,sizeof(h));
}
}g;
char str[44];
int i,n;
int main()
{
while(~scanf("%d",&n))
{
g.clear();
while(n--)
{
scanf("%s",str);
i=g.insert(str);
if(i<0)puts("OK");
else
{
printf("%s%d\n",str,g.d[i]);
++g.d[i];
}
}
}
return 0;
}
第四题:这题就是要求一个最长序列,满足第i个信封的长和宽都严格大于第i-1封的长和宽,并且第一封要大于给的的卡片
分析:我们按每个信封的宽排序,如果宽相同,再按长排序,然后,你应该会发现,这个跟最长地增字序列很像,为什么说是很像,而不是一样呢,因为对于宽相同的是不能放在一起的。。。我之前忽略这个问题,加了二分优化,反而挂了= =
代码:
#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int mm=111111;
struct data
{
int w,h,id;
}g[mm];
int f[mm],p[mm];
int i,j,k,ans,n,w,h;
bool cmp(data a,data b)
{
return a.w<b.w||(a.w==b.w&&a.h<b.h)||(a.w==b.w&&a.h==b.h&&a.id>b.id);
}
void out(int j)
{
if(j<0)return;
out(p[j]);
printf("%d%c",g[j].id,--ans?' ':'\n');
}
int main()
{
while(~scanf("%d%d%d",&n,&w,&h))
{
for(i=0;i<n;++i)
scanf("%d%d",&g[i].w,&g[i].h),g[i].id=i+1;
sort(g,g+n,cmp);
for(i=0;i<n;++i)
if(g[i].w>w&&g[i].h>h)f[i]=1;
else f[i]=-1e7;
for(i=0;i<n;++i)
for(p[i]=-1,j=0;j<i;++j)
if(g[j].w<g[i].w&&g[j].h<g[i].h&&f[j]+1>f[i])
{
f[i]=f[j]+1;
p[i]=j;
}
for(i=j=0;i<n;++i)
if(f[i]>f[j])j=i;
ans=f[j];
if(ans>0)
{
printf("%d\n",ans);
out(j);
}
else puts("0");
}
return 0;
}