[NOIP2008 提高组] 笨小猴

题目描述

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

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

输入格式:

一个单词,其中只可能出现小写字母,并且长度小于 100。

输出格式:

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

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

输入输出样例:

输入 #1:

error

输出 #1:

Lucky Word
2

输入 #2:

olympic

输出 #2

No Answer
0

说明/提示

【输入输出样例 1 解释】

单词 error 中出现最多的字母 r 出现了 33 次,出现次数最少的字母出现了 1 次,3-1=2,2 是质数。

【输入输出样例 2 解释】

单词 olympic 中出现最多的字母 i 出现了 1 次,出现次数最少的字母出现了 1 次,1-1=0,0 不是质数。

(本处原题面错误已经修正)

noip2008 提高第一题

思路:

  看到这道题,我们首先就是要找到一个字母出现次数最多是多少,最少出现次数是多少?  题目规定,输入最长为长度100的字符串a,我们可以用strlen(a)函数求出字符串a的长度t。

  我们怎么知道出现次数最多是多少?最少是多少呢?回想我们以前,输入一串数字之后,如何知道最多次数,最少次数?当然是桶了,但是我们输入的是字符啊,这个桶的下标不可能是一个字符。

  对,不可能!但是我们可以进行(int)类型的强制转换啊,我们知道,题目输入的字符串全都是小写字母,我们将输入的每一个字母进行(int)强制转换,变化为桶的下标,字母'a'的ASCII码为97,字母'z'的ASCII码为122,所以这个桶的下标应该在97~122之间,那0~96之间怎么办呢?是空的,那不有些浪费空间了吗。

  这样子来说,我们知道,'a'是26位英文字母的第一个,如果要下标为1,那么我们就可以将'a'-'a'+1当作桶的下标,如果字符是'b',那么'b'-'a'+1就等于2,这样来说,我们这个桶的下标空间就为1~26之间,为了保险起见,我们将桶的空间设置为30,都初始化为0.

  经过桶的计数之后,我们定义Max,Min,从桶的下标0~29之间找最大值和最小值,因为刚开始我们都初始化为0了,如果为0,那么代表输入的字符串里面没有这个编号的字符。所以,我们要判断如果不等于0的话,和Max,Min进行比较,找出最大值和最小值。

  找出最大值和最小值之后,我们要判断两者相减是否是一个质数Max-Min,如果是就输出Lucky Word,然后换行输出Max-Min的值。如果不是就输出No Answer,然后换行输出0.

  那我们怎么判断一个数是不是质数呢?

我们需要写一个判断一个整数是否是一个素数的函数:

            素数是什么呢?
            是除了1和它本身以外没有任何的因子.
            那么我们只要发现它的一个因子就可以说他不是素数,反之,返回true.
            因子是什么?
            一个数除以它的因子余数为0.
            我们可以根据这一点来进行判断,进行for枚举.
            那么范围是多少呢,1不是素数也不是合数,要在一开始进行特判.
            那么初始从=2开始,小于n吗?
            这样也可以,但是还可以进行优化.
            拿25来说,从2枚举到25,是不是浪费了很多.
            我们只要取25的根号,也就是5来当=2;<=5;
            为什么呢?
            因为5是他一个因子中最大的,只要看5以下的就行了.
            我们来细分以下,拿24为例:
                24=1*24;
                24=2*12;
                24=3*8;
                24=4*6;
                你看,我们给24开个根号,值在4~5之间,也就是说循环最多到4.
                循环过程:
                  24%2=0;
                  24%3=0;
                  24%4=0;
                你们可能会疑惑,还有12,8,6没有除余判断呢!
                其实根本没有必要,2,3,4和12,8,6相乘等于24,只要2,3,4除余为0,那么代表着12,8,6和24相除余数为0. 

  这样,我们的基本思路就讲到这里了,接下来给大家看一下代码吧!

代码:

#include<bits/stdc++.h> //万能头文件 
using namespace std; //批准使用std类 
int pd(int x){ //判断一个整数是不是素数 
	bool f=true; //刚开始定义为是素数 
    int k; //循环变量 
    if(x==1||x==0) //1既不是素数也不是合数,要首先排除掉 
	  f=false;  
    for(k=2;k<=sqrt(x);k++){ //循环遍历,sqrt函数是求一个整数开了根号后的值. 
        if(x%k==0){ //素数不能和1除外和他本身除外的任何数余数为0 
            f=false; //代表有一个因数了,就不是素数了 
			break; //退出 
        }
        else 
		  f=true; //是素数 
	}
    return f; //返回 
}
int main(){ //main主函数 
	char a[101]; //定义字符串 
	int f[30]={0},M='z'; //定义桶和最小的字母编号 
	cin.getline(a,101); //输入字符串 
	int t=strlen(a); //求出字符串的长度 
	for(int i=0;i<t;i++) //进行桶计数遍历 
	  f[a[i]-'a'+1]++,M=min(M,a[i]-'a'+1); //找出最小的字母编号和统计字母出现次数 
	int Max=f[M],Min=f[M]; //初始定义为最小字母编号出现次数 
	for(int i=1;i<30;i++){ //遍历桶 
		if(f[i]!=0){ //只要桶不为0 
			if(f[i]>Max) //如果有比Max更大的 
			  Max=f[i]; //赋值 
			if(f[i]<Min) //如果有比Min更小的 
			  Min=f[i]; //赋值 
		}
	}
	if(pd(Max-Min)) //判断最大值减去最小值的差是不是质数 
	  cout<<"Lucky Word\n"<<Max-Min<<endl; //输出 
	else //不是质数 
	  cout<<"No Answer\n0"<<endl; //输出 
	return 0; //结束 
}

总结:

  这道题是2008年提高组第一题,但是难度不算很高,只有普及1~2题的难度,考的知识点也很多:质数的判断,字符桶计数,找数组最大最小值。

  对于一个初学者来说,应该算是挺难的了!

题目链接:

[NOIP2008 提高组] 笨小猴 - 洛谷https://www.luogu.com.cn/problem/P1125

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

龙星尘

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值