前言
质数问题也算是入门的问题了,在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