算法学习之路2 质数问题

前言

质数问题也算是入门的问题了,在CSDN竞赛第五期中,前2题也跟质数问题存在关系,看了大佬们的解答,我的解题方式算是暴力的了。只能达到启蒙的作用,要做好还是要多刷题。

概念法

质数又称素数。一个大于1的自然数,除了1和它自身外,不能被其他自然数整除的数叫做质数;否则称为合数(规定1既不是质数也不是合数)。
根据概念下如下算法

int IsZhiShuV1(int n,int *count){
	for(int i=2;i<n;i++){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

很明显要求比较次数多,实际中是不会用的

启蒙阶段

实际中当比较的数超过一半就没有再比较下去的意义了
改成如下代码,比较数减少一半

int IsZhiShuV2(int n,int *count){
	int m=n/2+1;
	for(int i=2;i<m;i++){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

标准方法

根据上面只比较到总数的1/2就可以,那么1/3,1/4是不是也行呢,究竟多少就可以呢?这也是上学时的方法,比较到开根号就行,例如37,只要比较到6就行了,代码如下

int IsZhiShuV3(int n,int *count){
	int m=sqrt(n)+1;
	for(int i=2;i<m;i++){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

到这儿基本就是课上所学的了

优化1

上面普通方法中还是要遍历2~√n,其实可以发现,4,6可以跳过,如果能整除4 那么肯定能整除2,这样需要遍历的数可以减少一半
代码如下

int IsZhiShuV4(int n,int *count){
	if(n%2==0){
		(*count)++;
		return 0;
	}
	int m=sqrt(n)+1;
	for(int i=3;i<m;i+=2){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

优化2

上面2的倍数可以省略,那么3的倍数是不是也可以省略呢?
6n+0,6n+2,6n+3,6n+4, 都是2或3的倍数,那么需要检查的数就只有6n+1,6n+5
要检查的数又减少到1/3

int IsZhiShuV5(int n,int *count){
	if(n%2==0){
		(*count)++;
		return 0;
	}
	if(n%3==0){
		(*count)++;
		return 0;
	}
	int m=sqrt(n)+1;
	for(int i=5;i<m;i+=6){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	for(int i=7;i<m;i+=6){
		(*count)++;
		if(n%i==0){
			return 0;
		}
	}
	return 1;
}

后面可以考虑如何同时排除2,3,5的倍数,以此类推
需要变了的量为30个数种,排除2,3,5的倍数,30个数中要遍历8个,比1/3要少些,但明显复杂多了
比较高级的是构建素数表,2~√n中只要试探当中的质数就行了,但素数表需要构建,数多的话,构建好些,否则还是依次比就行了
如果是素数,加入到素数表中,给下一个数判断使用,

总结

我能想到的优化方案就这些,还有构建质数表的方案,有待考虑
用一个质数和一个合数进行测试看看比较次数

概念法:10007 是否质数:1 判断次数:10005
启蒙法:10007 是否质数:1 判断次数:5002
普通法:10007 是否质数:1 判断次数:99
优化法:10007 是否质数:1 判断次数:49
优化法2:10007 是否质数:1 判断次数:32
概念法:10201 是否质数:0 判断次数:100
启蒙法:10201 是否质数:0 判断次数:100
普通法:10201 是否质数:0 判断次数:100
优化法:10201 是否质数:0 判断次数:50
优化法2:10201 是否质数:0 判断次数:17

注意:
最后一个虽然是17,期望值应该是33,因为先跑的是6n+5(96+5=101),所以是17,
如果6n+5,6n+1依次跑,应该是33

CSDN竞赛第五期回顾

前2题跟本文还是有点关系的

1寻因找祖

寻找因子个数为n的最小整数x

暴力法 1~∞开始变量
因子数统计使用以下方法
遍历1~√n(不包括√n)就行
如12 ,开根号为3,遍历1,2都满足,数量翻倍(12,6也满足)就是4个
有因为 12%3==0 && 3*3!=12 ,结果再加2个,总就是6个因子
如16 ,开根号为4,遍历1,2,3,其中1,2满足,就有4个了
有因为 16%4==0 && 4*4==16 ,结果再加1个,总就是5个因子

这里有个小规律
如果因子个数是奇数,那必定是某个平方数,可以遍历1,22,32…,找起来快些
数量大的话会超时
高级点的就是自己凑因子,计算最小的数,想也想到了,有点复杂,可以看看其他大佬的解法,要会公式才行,还是要多练

2通货膨胀-x国货币

X国发行货币最高面额为n。 次高面额为n的因子。 以此类推。 X国最多发行多少种货币。

解法比较统一吧,从2~√n开始遍历,可以跳过2的倍数。
如n=12,可已整除2,则次高面额为6
然后6可以整除2,下一个次高面额为3
3是质数就结束了
一共有 12 ,6,3,1这4种面额
用循环或者递归统计次数就行

3莫名其妙的键盘

有一个神奇的键盘,你可以用它输入a到z的字符,然而每当你输入一个元音字母(a,e,i,o,u其中之一)的时候,已输入的字符串会发生一次反转! 比方说,当前输入了tw,此时再输入一个o,此时屏幕上的字符串two会反转成owt。 现给出一个字符串,若用该键盘输入,有多少种方法可以得到?

看了其他大神的解法,要用动态规划,本人还不熟悉,就不误导大家了

4三而竭

一鼓作气再而衰三而竭。 小艺总是喜欢把任务分开做。
小艺接到一个任务,任务的总任务量是n。
第一天小艺能完成x份任务。
第二天能完成x/k。 。。。
第t天能完成x/(k^(t-1))。
小艺想知道自己第一天至少完成多少才能完成最后的任务。

该题的测试用例为:n=59,k=9 输出 x=54

有点像等比数列问题,如果除不尽要向下取整
x+x/k+x/k2 +x/k3+…>=n
当x/ki为0时就结束了
看着可以用等比公式,但可能有问题,实际情况是不能有小数的,还有这么多年,公式我也忘了
暴力解,呵呵
初级暴力解,依次遍历1-n,看哪个值满足条件,就是X
优化暴力解,依次要遍历1,K,K2,K3…,要小于n,看从哪个开始满足条件,再从前面一项开始推
,如果K3满足
再从K2~K3遍历(这里可以再用二分法),获取满足条件的最小值
如果K3>n,那就遍历K2~n

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值