寒假第一次AK,但罚时爆炸名次依旧不高,大体总结如下:
问题:
一.没有算法的简单题不敢写,又不能想出正确的优化方案,在迟疑和思考中浪费了很多时间。
二.一些基础算法的变形写不对或者写很慢。
改进:
以后看到想不出算法却过掉一片的题要大胆写暴力(诸如此场的1007)。
在以后的算法学习中试着做一些基础算法的变形题,或多种算法相结合的题,锻炼自己的思维能力。
题目:
1001:
Problem A
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 35 Accepted Submission(s) : 32
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
看到第一个题目,你一定会觉得不虚此行~
问题来了:
有一个人要施展魔法,但是施展魔法的前提是咒语中‘a’字母的个数是三的倍数!是yes,否no!
Input
Output
Sample Input
jflkdsjsdfklja asdjfnmxcajda
Sample Output
no yes
签到水题,遍历字符串即可。
#include <bits/stdc++.h>
using namespace std;
int main(){
char str[1010];
while(scanf("%s",str) != EOF){
int i,len,cnt = 0;
len = strlen(str);
for(i=0 ;i<len ;i++){
if(str[i] == 'a')
cnt++;
}
if(cnt%3){
printf("no\n");
}
else{
printf("yes\n");
}
}
return 0;
}
1002:
Problem B
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 64 Accepted Submission(s) : 31
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
题目会给出一个字符串,该字符串最大长度为26。
如长度为3,那么该字符串只会由,a,b,c三个字母组成,当然这三个字母的顺序是打乱的。
之后会有多次询问,每次询问是两个字母char-A和char-B
如果char-A在char-B前面,则输出Before;反之,输出After。
Input
对于每组样例,首先输入一个n(2<=n<=26)
之后一个字符串
输入询问次数k(1<=k<=100)
接下来k行,每行两个字母char-A和char-B
Output
Sample Input
3 cab 2 c a b a
Sample Output
Before After
主要注意虽然只有三个字母,但每个字母的数量并不一定为1。所以只判断字符串的前三个元素是行不通的。
所以用了一个Hash来存每个字母第一次出现的顺序,然后每次询问输出即可。
#include <bits/stdc++.h>
using namespace std;
int Hash[30];
char str[30];
int main(){
int n;
while(scanf("%d",&n) != EOF){
scanf("%s",str);
memset(Hash,0,sizeof(Hash));
int len = strlen(str);
int i,cnt = 0;
for(i=0 ;i<len ;i++){
if(!Hash[str[i] - 'a']){
Hash[str[i] - 'a'] = ++cnt;
}
}
int k;
scanf("%d",&k);
char ch1,ch2;
while(k--){
cin>>ch1>>ch2;
if(Hash[ch1-'a'] < Hash[ch2-'a']){
printf("Before\n");
}
else{
printf("After\n");
}
}
}
return 0;
}
1003:
Problem C
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 104 Accepted Submission(s) : 26
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
Output
提示:做的时候,不要用到除法,用了除法就会WA噢!!聪明的你应该想到怎么做了吧!!
Sample Input
2 60 30 40 30
Sample Output
60 poor guy
因为平时分可以取小数,然后double型的二分挺麻烦,而且存在精度误差。
因为求满足A*y%+B*(1-y%) = 60的最小值,所以可以等式两端同时*100,把百分号去掉,即
A*y + B*(1-y) = 6000,然后移项,即 A*y = 6000 - B*(1-Y),然后等号右边是个确定的值。
然后让A在0~100的范围内二分搜索,使A*y的值等于右端即可。
借用了一下函数lower_bound。
#include <bits/stdc++.h>
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T--){
int B,y;
scanf("%d%d",&B,&y);
int aim = 6000 - B*(100-y);
if(100*y < aim){
printf("poor guy\n");
continue;
}
if(aim <= 0){
printf("0\n");
continue;
}
int grade[101],i;
for(i=0 ;i<101 ;i++){
grade[i] = i*y;
}
int t = lower_bound(grade,grade+101,aim) - grade;
cout << t << endl;
}
return 0;
}
1004:
Problem D
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 35 Accepted Submission(s) : 32
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
Output
Sample Input
2 2 3 2 30 60 50
Sample Output
0.600 0.667
开始还不敢写(做的时候只有两个人AC),题读了一遍又一遍,确定是有放回的拿球后,写了不到30秒,一次AC。
#include <bits/stdc++.h>
using namespace std;
int main(){
int T;
scanf("%d",&T);
while(T--){
int a,b,k;
scanf("%d%d%d",&a,&b,&k);
double ans = 1.0*b/(a+b);
printf("%.3f\n",ans);
}
return 0;
}
1005:
Problem E
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 104 Accepted Submission(s) : 29
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
Input
如果输入Query,则按照要求输出内容
如果输入Add,则后面跟一个m(m<=10),然后增加m个人的身高
Output
每组数据之间输出一个空行。
提示:最后一个例子后面没有空行
Sample Input
5 1.72 1.75 1.73 1.62 1.55 5 Query Add 1 1.64 Query Add 2 1.98 1.88 Query 7 1.52 1.87 1.67 1.77 1.74 1.59 1.64 3 Query Add 1 1.50 Query
Sample Output
1.69 1.68 1.72 1.68 1.66
树状数组和线段树中的裸题。
主要输出格式有点坑。
#include <bits/stdc++.h>
using namespace std;
const double INF = 1e8;
const int maxn = 2110;
double tree[maxn];
int lowbit(int x){
return x&(-x);
}
double getsum(int pos){
double res = 0;
while(pos>0){
res += tree[pos];
pos -= lowbit(pos);
}
return res;
}
void add(int pos,double num){
while(pos < maxn){
tree[pos] += num;
pos += lowbit(pos);
}
}
int main(){
int _ = 0,n;
while(scanf("%d",&n) != EOF){
if(_++){
printf("\n");
}
int i;
for(i=0 ;i<maxn ;i++)
tree[i] = 0;
double x,vmin = INF,vmax = 0;
for(i=1 ;i<=n ;i++){
scanf("%lf",&x);
if(x<vmin)
vmin = x;
if(x>vmax)
vmax = x;
add(i,x);
}
int k,m;
double ans = 0;
char str[55];
scanf("%d",&k);
while(k--){
scanf("%s",str);
if(str[0] == 'Q'){
ans = getsum(n) - vmin - vmax;
ans /= (n-2);
printf("%.2f\n",ans);
}
else{
double y;
scanf("%d",&m);
n += m;
for(i=1 ;i<=m ;i++){
scanf("%lf",&y);
if(y<vmin)
vmin = y;
if(y>vmax)
vmax = y;
add(1,y);
}
}
}
}
return 0;
}
Problem F
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 96 Accepted Submission(s) : 21
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
有一次小明妈妈让小明去买一些既好吃又实惠的桃子,小明来到水果店,发现商店在搞活动买桃子赠送葡萄粒,水果店中有n(1<=n<=100)种桃子。
商家活动规则如下:当找还你钱的时候,用葡萄粒代替人民币中的角和分,当然一次最多只能找还99个葡萄粒,因为1元等于10角或100分。
这时候,心里只有葡萄了,完全忘记了妈妈给他说的话(“既好吃又实惠”),所以他也不管是否实惠了,而且他又嫌麻烦,就只买了一种桃子,这完全是因为他只希望最大限度的要葡萄,但是他只带了s(1<=s<=100)元钱。
由于他心思全放在葡萄上了,所以在这上面变得聪明了,但是他只能买一次!
Input
紧接着n行,每行两个整数代表每种桃子的价格,x,y(1<=x<=100; 0<=y<=100),两个数分别代表元和分;
Output
Sample Input
5 10 3 90 12 0 9 70 5 50 7 0 5 100 3 50 4 20 7 2 9 0 6 10
Sample Output
50 98
做这题的时候AC率不太高,但读完题又感觉是一个水题,然后WA了两次后就先做的后面,回头再看时发现原来同种种类的桃子你买的数量不同,所得的葡萄也不同。
然后改了一下,AC。
#include <bits/stdc++.h>
using namespace std;
int main(){
int n,s;
while(scanf("%d%d",&n,&s) != EOF){
s *= 100;
int x,y,i,vmax = 0;
for(i=0 ;i<n ;i++){
scanf("%d%d",&x,&y);
int price = x*100 + y;
int tem = price;
while(tem<=s){
int p = (s-tem)%100;
if(p > vmax)
vmax = p;
tem += price;
}
}
if(!vmax)
printf("-1\n");
else{
cout << vmax << endl;
}
}
return 0;
}
1007:
Problem G
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 63 Accepted Submission(s) : 18
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
有一天,他来到饭店解决午饭,由于他很饿,所以他一口气点了N盘菜(编号1..N),打算把这些菜全部解决。
这个饭店的规矩很奇怪,开始的M盘菜(1..M)总是一起上,且从左到右排成一排,接下来则是桌上的菜每被吃掉一盘就上一盘(即保持桌面上一直是M盘菜),直到菜上齐。ZXJ总是吃最左边的那一盘。每当有一盘新的菜上来,ZXJ会根据自己的喜好,让服务员将其放在从左到右第K的位置。
求ZXJ吃菜的顺序。
Input
接下来一行有N-M个整数Ki(1<=Ki<=M),代表新上的菜的位置。
Output
输出为一行,每两个数字之间用空格隔开,行末无空格。
Sample Input
5 2 1 2 2
Sample Output
1 3 2 4 5
最后做的这道题,一开始不敢写暴力,感觉复杂度太高,然后一直想优化办法,然后走入了预处理的歧途,用vector模拟WA了十发,最后实在找不到可以改进的地方(WA十次能改的都改了),加上还剩十几分钟的时间,死马当活马医,写了几分钟暴力.....然后.....一次AC。
后来翻statistic,发现大家都是31ms的暴力....qwq....
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1010;
int a[maxn];
int main(){
int n,m;
while(scanf("%d%d",&n,&m) != EOF){
memset(a,0,sizeof(a));
int i,j,pos;
for(i=1 ;i<=m ;i++){
a[i] = i;
}
int cnt = m;
for(i=1 ;i<=n-cnt ;i++){
scanf("%d",&pos);
pos = pos + i;
for(j=m+1 ; j>=pos ;j--){
a[j] = a[j-1];
}
m++;
a[pos] = m;
}
printf("1");
for(i=2 ;i<=n ;i++){
printf(" %d",a[i]);
}
printf("\n");
}
return 0;
}
1008:
Problem H
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 72 Accepted Submission(s) : 27
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
只要你凑齐三个可可可乐的瓶盖就可以换一瓶可可可乐。
ZXJ同学看到这个广告后老激动了,打算买n瓶可乐送给集训队的队员,可是让他为难的是他至少买几瓶才能得到n瓶可可可乐呢?
(注意每瓶可可可乐不可能出现两个瓶盖哦)
Input
Output
Sample Input
15084
Sample Output
10057
好像是我小学时做过的数学题....当然n没这么大...
#include <bits/stdc++.h>
using namespace std;
int main(){
int n;
while(scanf("%d",&n) != EOF){
int sum = 0;
sum = n/3*2 + n%3;
if(n%3 == 0 && n)
sum++;
cout << sum << endl;
}
return 0;
}
1009:
Problem I
Time Limit : 3000/1000ms (Java/Other) Memory Limit : 65535/32768K (Java/Other)
Total Submission(s) : 66 Accepted Submission(s) : 30
Font: Times New Roman | Verdana | Georgia
Font Size: ← →
Problem Description
这里我们用zero,one,two,three,…,nine,10个英文单词分别表示数字0,1,2,…,9。
Input
每组数据输入两个字符串a,b,只由zero,…,nine,10个英文单词组成,每个字符串长度不大于24。
Output
Sample Input
onetwothreefour oneoneoneone onezerozero onezerozerozero one two
Sample Output
twothreefourfive oneonezerozero three
刚好上一场结束后学习了string的用法,现学现用,轻松解决字符串匹配问题,1次AC。
#include <bits/stdc++.h>
using namespace std;
char str1[35],str2[35];
map<string,int> mp1;
char mp2[20][10] = {"zero","one","two","three","four","five","six","seven","eight","nine"};
void init(void){
mp1["zero"] = 10;
mp1["one"] = 1;
mp1["two"] = 2;
mp1["three"] = 3;
mp1["four"] = 4;
mp1["five"] = 5;
mp1["six"] = 6;
mp1["seven"] = 7;
mp1["eight"] = 8;
mp1["nine"] = 9;
}
int main(){
init();
string s1 = "";
while(scanf("%s%s",str1,str2) != EOF){
int len1,len2,i,cnt;
long long a = 0,b = 0;
len1 = strlen(str1);
len2 = strlen(str2);
for(i=0 ;i<len1 ;i++){
s1 += str1[i];
if(mp1[s1]>0){
if(mp1[s1] != 10)
a = a*10 + mp1[s1];
else
a = a*10;
s1 = "";
}
}
s1 = "";
for(i=0 ;i<len2 ;i++){
s1 += str2[i];
if(mp1[s1]>0){
if(mp1[s1] != 10)
b = b*10 + mp1[s1];
else
b = b*10;
s1 = "";
}
}
int ans = a + b;
if(ans == 0){
printf("zero\n");
continue;
}
cnt = 0;
int p = ans;
while(p>0){
p /= 10;
cnt++;
}
while(cnt){
int tem = 1;
for(i=1 ;i<cnt ;i++){
tem *= 10;
}
printf("%s",mp2[ans/tem]);
ans %= tem;
cnt--;
}
printf("\n");
}
return 0;
}