寒假训练赛(三) 自我总结

寒假第一次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

输入有多组,每组一串咒语(全是小写字母)(长度小于1000)

Output

输出yes or no

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

根据情况输出Before和After

Sample Input

3
cab
2
c a
b a

Sample Output

Before
After
写了5分钟,一次AC。

主要注意虽然只有三个字母,但每个字母的数量并不一定为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

ZXJ除了挂科外什么都不怕,平时喜欢在寝室里看看小电影,打打游戏。他还有一项特殊的技能:能够准确的预测自己期末的卷面成绩。一到期末ZXJ就开始紧张了。因为平时表现不好,担心平时分太低导致期末挂科。于是开始不断的给老师打电话,求老师多给点平时分(分数为百分制)。假设平时分为A , 考试分数为B ,那么最后总分是 A*y%+B*(1-y%)

Input

第一行输入整数t(0<t<=1000),表示接下来有几个案例,第二行输入预测卷面成绩整数x(0<=x<=100),和平时分占的比例整数y(0=<y<=100)。

Output

输出保证ZXJ不挂的最低平时分,如果无论平时分多高都不能保证ZXJ不挂科就输出poor guy。(答案向上取整)
提示:做的时候,不要用到除法,用了除法就会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

ZXJ是神界的审判之神,一天他智慧之神犯下滔天大祸,理应形神俱灭,但是智慧之神为了神界创立立下了汗马功劳,于是ZXJ决定给智慧之神一次避免死亡的机会:他给了这个神a个白球,b个黑球,若智慧之神在第k次取到黑球,则免除智慧之神的死刑,否则执行死刑,你能算出智慧之神存活的概率么?

Input

输入数据有多行组成,首先是一个整数T,表示测试实例的个数,然后是T行数据,每行有三个数据a,b,k,分别表示a个白球,b个黑球和拿k次球。题目保证所有的数据合法。数据在50000以内

Output

输出一个小数,保留3位有效数字。

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

集训队每过一段时间都会纳入新的ACMer,队长二狗没吃药的时候就想知道集训队队员的平均身高。哦,不算上最高和最低的。

Input

本题目包含多组测试数据,请处理至EOF。第一行请输入集训队原有的队员个数n,第二行输入n(n<=1000)个队员的身高。第三行输入一个整数q(q<=100000),接下来有q行输入。
如果输入Query,则按照要求输出内容
如果输入Add,则后面跟一个m(m<=10),然后增加m个人的身高

Output

对于每个Query 需要输出当前队员的平均身高,平均身高要求保留两位小数。
每组数据之间输出一个空行。

提示:最后一个例子后面没有空行

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;
}


1006:

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,s;
紧接着n行,每行两个整数代表每种桃子的价格,x,y(1<=x<=100; 0<=y<=100),两个数分别代表元和分;

Output

他能得到最大的葡萄粒的数量(当他买不到任何葡萄的时候输出-1)。

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

ZXJ是一个大胃王,每顿饭都要吃好多。
有一天,他来到饭店解决午饭,由于他很饿,所以他一口气点了N盘菜(编号1..N),打算把这些菜全部解决。
这个饭店的规矩很奇怪,开始的M盘菜(1..M)总是一起上,且从左到右排成一排,接下来则是桌上的菜每被吃掉一盘就上一盘(即保持桌面上一直是M盘菜),直到菜上齐。ZXJ总是吃最左边的那一盘。每当有一盘新的菜上来,ZXJ会根据自己的喜好,让服务员将其放在从左到右第K的位置。
求ZXJ吃菜的顺序。

Input

第一行是两个整数N,M(1<=M<N<=1000)。
接下来一行有N-M个整数Ki(1<=Ki<=M),代表新上的菜的位置。

Output

输出ZXJ吃菜的顺序。
输出为一行,每两个数字之间用空格隔开,行末无空格。

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

有多组样例,每一行输入一个正整数n(0<=n<=100000000)

Output

每一行输出一个正整数表示ZXJ同学真正所需要购买的可可可乐数。

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

本次四国对抗赛的最后,是一道A+B的题目:
这里我们用zero,one,two,three,…,nine,10个英文单词分别表示数字0,1,2,…,9。

Input

多组测试数据,每组单独一行。
每组数据输入两个字符串a,b,只由zero,…,nine,10个英文单词组成,每个字符串长度不大于24。

Output

每组数据单独输出一行,计算a+b得到的结果,只由zero,…,nine组成。

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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值