地址(需内网):http://acm.hit.edu.cn/contest/141

第一次正式的打这类比赛,总体来说还是比较菜。
总共A了四道题,Ranking NO.25,Penalty 17:41:57,First Blood 1。

简谈下此次比赛吧。

A题

水题,字符串处理,读题有坑。WA了9发。
大致题意;定义一个q-string,重点长度大于1,按照step1删去末尾e,step2将辅音字母后的y改成i,加上er。

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>

using namespace std;
int main()
{
int t;
scanf("%d",&t);
int cas=0;
while(t--)
{
char s[10086];
scanf("%s",s);
int len=strlen(s);
int k=len-1;
if(s[k]!='e'&&s[k]!='y')
{
printf("Case #%d: %ser\n",++cas,s);
continue;
}
else
{
while(s[k]=='e'&&k>=0)
{
s[k]='\0';
k--;
}
}
if(k==-1) printf("Case #%d: eer\n",++cas);
else if(k<=1) printf("Case #%d: %ser\n",++cas,s);
else {
if(s[k]!='y') printf("Case #%d: %ser\n",++cas,s);
else if(s[k-1]!='a'&&s[k-1]!='e'&&s[k-1]!='i'&&s[k-1]!='o'&&s[k-1]!='u')
{
s[k]='i';
printf("Case #%d: %ser\n",++cas,s);
}
else printf("Case #%d: %ser\n",++cas,s);
}
}
return 0;
}

B题

题意:数字黑洞,除了四位数字相同的(包括0)四位数(不足的补0),四个数字降序和升序组成新四位数相减,最终会在6174无限循环。求计算过程。
思路:转换成字符串处理。(没注意数据范围被坑了几次)

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
#include <bits/stdc++.h>

using namespace std;

int cmp(int a,int b)
{
return a>b;
}

int ce[4],de[4];
char a[4];

void div(char mmp[])
{
de[0]=mmp[0]-'0';
de[1]=mmp[1]-'0';
de[2]=mmp[2]-'0';
de[3]=mmp[3]-'0';
for(int i=0;i<4;i++){
ce[i]=de[i];
}
sort(ce,ce+4);
sort(de,de+4,cmp);
}

int main()
{
int t;
scanf("%d",&t);
int cas=0;
while(t--)
{
int num;
scanf("%d",&num);
printf("Case #%d:\n",++cas);
if(num==0){
printf("0000 - 0000 = 0000\n");
continue;
}
for(int i=0;i<4;i++){
a[i]=(num%10)+'0';
num/=10;
}
a[4]='\0';
char idx=a[0];
if(idx==a[1]&&idx==a[2]&&idx==a[3])
{
printf("%s - %s = 0000\n",a,a);
continue;
}
int flag=-1;
while(1)
{
div(a);
int fr=de[0]*1000+de[1]*100+de[2]*10+de[3];
int la=ce[0]*1000+ce[1]*100+ce[2]*10+ce[3];
int tmp=fr-la;
if(tmp==6174) flag=1;
if(tmp==6174&&flag==1) flag=2;
for(int i=0;i<4;i++){
a[i]=(tmp%10)+'0';
tmp/=10;
}
printf("%d%d%d%d - %d%d%d%d = %04d\n",de[0],de[1],de[2],de[3],ce[0],ce[1],ce[2],ce[3],fr-la);
if(flag==2) break;
}
}
return 0;
}

C题

简单贪心,每次取最小的两个数相加即可。
数据范围较大n<=100000
错误思路:快排,每次快排的效率是O(n^2 logn),铁定超时系列。
正确做法:堆,用优先队列即可实现。
暴力做法:据观察,每个数不超过1000,十万个数相加不超过1亿,故可以采取计数排序的思想,暴力扫。

AC代码(暴力做法):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <bits/stdc++.h>

using namespace std;

int a[100000000];

int main()
{
int n;
while(scanf("%d",&n)&&n)
{
int ans=0;
memset(a,0,sizeof(a));
for(int i=0; i<n; i++)
{
int x;
scanf("%d",&x);
a[x]++;
}
int cnt=n;
int i=0;
int tmp=-1;
while(cnt!=1)
{
if(a[i]==0)
{
i++;
continue;
}
// printf("%d ",i);
if(a[i]==1&&tmp==-1)
{
tmp=i;
a[i]--;
continue;
}
if(a[i]==1&&tmp!=-1)
{
ans+=tmp+i;
a[i+tmp]++;
tmp=-1;
cnt--;
a[i]--;
if(cnt==1) break;
else continue;
}
if(a[i]>=2&&tmp==-1)
{
a[2*i]++;
a[i]-=2;
ans+=2*i;
cnt--;
if(cnt==1) break;
else continue;
}
if(a[i]>=2&&tmp!=-1)
{
a[i+tmp]++;
ans+=i+tmp;
a[i]--;
cnt--;
tmp=-1;
if(cnt==1) break;
}
//printf("%d\n",ans);
}
printf("%d\n",ans);
}
return 0;
}

K题

其实这题是没看懂的,莫名其妙拿了一血。

题意:给定一个序列,求一个序列,其中任意两个数的最大公因数大于1,计算其最大长度。

做法1:由于数据是随机生成的,奇偶各一半,直接计算偶数个数即可。
(我采用的这种做法,水数据2333)

正解:计算2-sqrt(maxnum)之间所有素数的倍数,取其最大值。

AC代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <bits/stdc++.h>

using namespace std;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int a[n];
for(int i=0;i<n;i++) scanf("%d",&a[i]);
int cnt=0;
for(int i=0;i<n;i++){
if(a[i]==2)cnt++;
else if(a[i]%2==0)cnt++;
}
printf("%d\n",cnt);
}
return 0;
}