信息学奥赛一本通(C++版)going

第一部分 C++语言

第六章 数组 第一节 函数

	这一节算是错题罗列,待解决,以防它们被淹没而悬而未决。

甲流病人初筛

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 9941 通过数: 5772

【题目描述】
目前正是甲流盛行时期,为了更好地进行分流治疗,医院在挂号时要求对病人的体温和咳嗽情况进行检查,对于体温超过37.5度(含等于37.5度)并且咳嗽的病人初步判定为甲流病人(初筛)。现需要统计某天前来挂号就诊的病人中有多少人被初筛为甲流病人。

【输入】
第一行是某天前来挂号就诊的病人数n。(n<200)
其后有n行,每行是病人的信息,包括三个信息:姓名(字符串,不含空格,最多8个字符)、体温(float)、是否咳嗽(整数,1表示咳嗽,0表示不咳嗽)。每行三个信息之间以一个空格分开。

【输出】
按输入顺序依次输出所有被筛选为甲流的病人的姓名,每个名字占一行。之后在输出一行,表示被筛选为甲流的病人数量。

【输入样例】

5
Zhang 38.3 0
Li 37.5 1
Wang 37.1 1
Zhao 39.0 1
Liu 38.2 1

【输出样例】

Li
Zhao
Liu
3

【我的代码】


#include<string>
#include<iostream>
using namespace std;
int main()
{
	int n;
	cin>>n;
	string a[200];
	float b[200];
	int c[200];
	int t=0;
	for(int i=0;i<n;i++)
	{
		cin>>a[i];cin>>b[i];cin>>c[i];
	}
	for(int i=0;i<n;i++)
	if(b[i]>=37.5&&c[i]==1){cout<<a[i]<<endl;t++;}
	cout<<t<<endl;
	return 0;
}

实在疑惑,为啥我处理名字用char型二维数组不OK,只有string型一维数组提交过得了,呜呜呜

统计单词数

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 12998 通过数: 4041

【题目描述】
一般的文本编辑器都有查找单词的功能,该功能可以快速定位特定单词在文章中的位置,有的还能统计出特定单词在文章中出现的次数。
现在,请你编程实现这一功能,具体要求是:给定一个单词,请你输出它在给定的文章中出现的次数和第一次出现的位置。注意:匹配单词时,不区分大小写,但要求完全匹配,即给定单词必须与文章中的某一独立单词在不区分大小写的情况下完全相同(参见样例1),如果给定单词仅是文章中某一单词的一部分则不算匹配(参见样例2)。

【输入】
第 1 行为一个字符串,其中只含字母,表示给定单词;
第 2 行为一个字符串,其中只可能包含字母和空格,表示给定的文章。

【输出】
只有一行,如果在文章中找到给定单词则输出两个整数,两个整数之间用一个空格隔开,分别是单词在文章中出现的次数和第一次出现的位置(即在文章中第一次出现时,单词首字母在文章中的位置,位置从0开始);如果单词在文章中没有出现,则直接输出一个整数-1。

【输入样例】

To
to be or not to be is a question

【输出样例】

2 0

【提示】
样例输入:
样例 #2:

to
Did the Ottoman Empire lose its power at that time

样例输出:
样例 #2:

-1

【我的代码】
这道题着实花了我好多功夫,设计了三个代码,自以为都OK,但是实际提交只过了一个。
【方案一】失败

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
	char a[100],b[10000];
	char *c;
	int k=0,t=0,m;
	gets(a);gets(b);
	for(int i=0;i<strlen(a);i++)
		if(a[i]>='A'&&a[i]<='Z')a[i]+=32;
	for(int i=0;i<strlen(b);i++)
		if(b[i]>='A'&&b[i]<='Z')b[i]+=32;
	int l=0;
	char s[10000];
	for(int i=0;i<strlen(b);i++)
	{
		if(b[i]==' ')
		{	for(int j=i+1;;j++)
			if(b[j]!=' ')	{s[l]=' ';l++;i=j-1;break;}
		}
		else {s[l]=b[i];l++;}
	}
	s[l]='\0';
	c=strtok(s," ");
	while(c!=NULL)
	{
		if(strcmp(c,a)==0){t++;if(t==1)m=k;}
		k++;
		c=strtok(NULL," ");
	}
	if(t!=0)
	cout<<t<<" "<<m<<endl;
	else cout<<"-1"<<endl;
	return 0;
}

【方案二】失败

#include<iostream>
#include<string>
#include<cstdio>
using namespace std;
int main()
{
	string s;
	cin>>s;
	for(int i=0;i<s.size();i++)
		if(s[i]>=97)s[i]-=32;
	string a;
	cin>>a;//文章中每个单词的输入
	char c;
	c=getchar();//利用getchar()来处理空格与结束输入
	for(int i=0;i<a.size();i++)
		if(a[i]>=97)a[i]-=32;
	int k=0,m,t=0;
	if(s==a){t++;if(t==1)m=k;}
	while(c!='\n')
	{
	cin>>a;
	c=getchar();
	k++;
	for(int i=0;i<a.size();i++)
		if(a[i]>=97)a[i]-=32;
	if(s==a){t++;if(t==1)m=k;}//string 型可直接==比较
	}
	if(t==0) cout<<"-1"<<endl;
	else
	cout<<t<<" "<<m<<endl;
	return 0;
}

【方案三】成功(但是费脑子理解啊)

#include <iostream>
#include <string>
using namespace std;
int main()
{
	string str1,str2;//查找串,目标串
	int i,j,cnt = 0,t = 0,len1,len2;
	getline(cin,str1);
	getline(cin,str2);
	len1 = str1.size();
	len2 = str2.size();
	for (i = 0; i < len2 - len1; ++i)
	{
		for (j = 0; j < len1; ++j)
		{
			if (toupper(str2[i+j]) != toupper(str1[j])) break;
			if (i > 0 && str2[i-1] != ' ') break;
		}
		if (j == len1 && (str2[i+j] == ' ' || i + j == len2))
		{
			++cnt;
			if (cnt == 1) t = i;
		}
	}
	if (cnt == 0)
		cout << "-1";
	else
		cout << cnt << ' ' << t;
	return 0;
}

机器翻译

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 8106 通过数: 3606

【题目描述】
小晨的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。

这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有M个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M−1,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为N个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

【输入】
共2行。每行中两个数之间用一个空格隔开。
第一行为两个正整数M和N,代表内存容量和文章的长度。
第二行为N个非负整数,按照文章的顺序,每个数(大小不超过1000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。

【输出】
共1行,包含一个整数,为软件需要查词典的次数。

【输入样例】

3 7
1 2 1 5 4 4 1

【输出样例】

5

【提示】

样例输入:

样例 #2:

2 10

8 824 11 78 11 78 11 78 8 264

样例输出:

样例 #2:

6

提示

输入输出样例 1 说明:

整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况:

空:内存初始状态为空。
1.1:查找单词1并调入内存。
2.1 2:查找单词2并调入内存。
3.1 2:在内存中找到单词1。
4.1 2 5:查找单词5并调入内存。
5.2 5 4:查找单词4并调入内存替代单词1。
6.2 5 4:在内存中找到单词4。
7.5 4 1:查找单词1并调入内存替代单词2。

共计查了5 次词典。

【我的代码】

#include<iostream>
using namespace std;
int main()
{
	int m,n,x=0,y=0;
	cin>>m>>n;
	int a[1000],b[10000];
	for(int i=0;i<m;i++)
	b[i]=-1; 
	for(int i=0;i<n;i++)
	{
		cin>>a[i];
		for(int h=0;h<m;h++)
		{
			if(b[h]!=a[i]&&b[h]>=0)y++;
			if(b[h]==a[i])break;
			if(b[h]<0)
			{x++;b[h]=a[i];break;}
		}
		if(y==m)
		{
		x++;
		for(int l=0;l<m-1;l++)b[l]=b[l+1];
		b[m-1]=a[i];
		}
		y=0;
	}
	cout<<x<<endl;
	return 0;
}

注:每次循环y都得归0!

Vigenère密码

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 5910 通过数: 3315

【题目描述】

6世纪法国外交家Blaise de Vigenère设计了一种多表密码加密算法——Vigenère密码。Vigenère密码的加密解密算法简单易用,且破译难度比较高,曾在美国南北战争中为南军所广泛使用。

在密码学中,我们称需要加密的信息为明文,用M
表示;称加密后的信息为密文,用C表示;而密钥是一种参数,是将明文转换为密文或将密文转换为明文的算法中输入的数据,记为k。 在Vigenère密码中,密钥k是一个字母串,k=k1k2…kn。当明文M=m1m2…mn时,得到的密文C=c1c2…cn,其中ci=mi®ki,运算®的规则如下表所示:
在这里插入图片描述
Vigenère加密在操作时需要注意:

1.®运算忽略参与运算的字母的大小写,并保持字母在明文M中的大小写形式;

2.当明文M的长度大于密钥k的长度时,将密钥k
重复使用。
例如,明文M=Helloworld,密钥k=abc时,密文C=Hfnlpyosnd。

【输入】
第一行为一个字符串,表示密钥k,长度不超过100
,其中仅包含大小写字母。第二行为一个字符串,表示经加密后的密文,长度不超过1000,其中仅包含大小写字母。
对于100%的数据,输入的密钥的长度不超过100,输入的密文的长度不超过1000,且都仅包含英文字母。

【输出】
输出共1行,一个字符串,表示输入密钥和密文所对应的明文。

【输入样例】

CompleteVictory
Yvqgpxaimmklongnzfwpvxmniytm

【输出样例】

Wherethereisawillthereisaway

【我的代码】


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int main()
{
	char k[100],C[1000],M[1000];
	gets(k);gets(C);
	for(int i=0;i<strlen(k);i++)
		if(k[i]>='a')k[i]-=32;
	for(int i=0;i<strlen(C);i++)
	{
			if(C[i]>=65&&C[i]<=90)
			{
			M[i]=C[i]-(k[i%strlen(k)]-65);
			if(C[i]<k[i%strlen(k)])M[i]+=26;
			}
			else
			{ 
				C[i]-=32;
				M[i]=C[i]-(k[i%strlen(k)]-65);
				if(C[i]<k[i%strlen(k)])M[i]+=26;
				M[i]+=32;
			}
	}
	for(int i=0;i<strlen(C);i++)
	cout<<M[i];
	return 0;
}

到现在,还是没找到那一个测试点不过答案错误的原因!我连strupr函数都没敢用,这测试系统啊啊啊~

笨小猴

时间限制: 1000 ms 内存限制: 65536 KB
提交数: 12816 通过数: 4555

【题目描述】
笨小猴的词汇量很小,所以每次做英语选择题的时候都很头疼。但是他找到了一种方法,经试验证明,用这种方法去选择选项的时候选对的几率非常大!

这种方法的具体描述如下:假设maxn是单词中出现次数最多的字母的出现次数,minn是单词中出现次数最少的字母的出现次数,如果maxn-minn是一个质数,那么笨小猴就认为这是个Lucky Word,这样的单词很可能就是正确的答案。

【输入】
只有一行,是一个单词,其中只可能出现小写字母,并且长度小于100。

【输出】

共两行,第一行是一个字符串,假设输入的的单词是Lucky Word,那么输出“Lucky Word”,否则输出“No Answer”;

第二行是一个整数,如果输入单词是Lucky Word,输出maxn-minn的值,否则输出0。

【输入样例】

error

【输出样例】

Lucky Word
2

【提示】

样例输入:

样例 #2:

olympic

样例输出:

样例 #2:

No Answer
0

【我的代码】未通过两个测试点

#include<iostream>
#include<cstdio>
#include<cstring>
int prime(int);
using namespace std;
int main()
{
	char a[100];
	gets(a);
	int t=0;
	int max=1,min=strlen(a);
	for(int i=0;i<strlen(a);i++)
	{	for(int j=0;j<strlen(a);j++)
			if(a[j]==a[i])t++;
		if(t>max)max=t;
		if(t<min)min=t;
		t=0;
	}
	if(prime(max-min))
		cout<<"Lucky Word"<<endl<<max-min<<endl;
	else cout<<"No Answer"<<endl<<"0"<<endl;
	return 0;
}
int prime(int x)
{
if(x==0||x==1)return 0;
if(x==2) return 1;
for(int i=2;i*i<=x;i++)
	if(x%i==0)return 0;
return 1;
}

just,over
wish continue

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值