标签:return gcd 公倍数 ---- int 最大公约数 base ans 模板
1.快速幂模板。
快速幂的模板大家应该是不陌生的,之前我一直是直接记模板的,今天来具体解释一下快速幂模板的意义。
不取模的模板如下:(取模自己修改一下)
ll fp(ll a,ll b){
ll ans=1;
ll base=a;
while(b!=0){
if(b&1!=0)
ans=ans*base;
base*=base;
b>>=1;
}
return ans;
}
如何理解该模板:
首先快速幂的基本思想是分治和二进制,我们直接带入一个例子更好理解,如计算2的11次方。
首先ans=1,base=2,b=11;我们知道11的二进制是1011;if(b&1!=0) ans=ans*base;这一个语句的作用是,根据幂的二进制来决定是否要乘入答案,base*=base;的作用是让基数翻倍;
拿2的11次方来说,①b=1011,ans=1,base=2 ②ans=1*2,base=2*2,b=101, ③ans=2*2*2,base=2*2*2*2,b=10 ④ans=2*2*2,base=2*2*2*2*2*2*2*2,b=1 ⑤ ans=2*2*2*2*2*2*2*2*2*2*2,b=0 ⑥跳出for循环,结束。
这么理解一下,快速幂的模板再也不用四级硬背了,信手拈来。
由上可见,达到了计算2的11次方的目的,最坏的复杂度也只为O(logn),而暴力的复杂度是O(n),快速幂简直是完美情人!
2.求两个数的最大公约数模板
(1)经典欧几里得算法(辗转相除法)一般用这个就够了
int gcd(int a,int b){
if(b==0) return a;
else return gcd(b,a%b);
}
如何理解记忆:
写题最讨厌的就是找代码模板了,所以我们要做到让这些常用代码印在心中!
其实就是两个数反复换位相互求余,当b为0时,a即为最大公因数。
如计算8和12的最大公因数,gcd(8,12),gcd(12,8),gcd(8,4),gcd(4,0)。
推导一遍就很容易记下。欧几里得算法依旧是复杂度为O(logn)的优秀算法。
(2)stein算法(如果不能A题,用这个改进一下)
针对欧几里德算法在对大整数进行运算时,需要试商导致增加运算时间的缺陷而提出的改进算法。
ll gcd(ll u,ll v)
{
if (u == 0) return v;
if (v == 0) return u;
if (~u & 1)
{
if (v & 1)
return gcd(u >> 1, v);
else
return gcd(u >> 1, v >> 1) << 1;
}
if (~v & 1)
return gcd(u, v >> 1);
if (u > v)
return gcd((u - v) >> 1, v);
return gcd((v - u) >> 1, u);
}
直接贴代码,因为也不常用,没有去理解,用得上的机会比较少。
3.最小公倍数。
求两个数的最小公倍数算法是基于gcd算法的基础上的。
int lcm(int a,int b){
return a/gcd(a,b)*b;
}
如何理解记忆:
这个还是比较简单的,就是用一个数去除以最大公因数得到的结果,再乘以另一个数,就可以得到这两个数的最小公倍数。
4.求一个数的所有因数之和。
(包括一,不包括本身)算法的解释都在代码里面了,比较好理解。
int factorSum(int n){
int sum=0;
for (int i=1;i*i<=n;i++){//折半除,降低复杂度
if (n%i==0){
if (i==1||i*i==n) sum+=i;//如果这个因数为1或者刚好是该数的平方根,只加一个就可以了。
else sum+=i+n/i;//加上该因数和该因数的关联因数。
}
}
return sum;
}
5.素数判断
(1)一般情况下,简单的判断素数代码。
bool is_prime(int n){
if(n<=1) return false;
for(int i=2;i*i<=n;i++)
if(n%i==0) return false;
return true;
}
这个比较好理解,只要有除1以外的因数直接返回false,否则返回true
复杂度O(根号n),这个模板的时间复杂度对于10的12次方以内的数的判断是没有问题的
(2)更快速的方法
这两个方法在数据不是很大时对比不明显,数据很大时可以体现出方法2的优越性。代码如下:
bool isPrime(int a) {
if(a == 1) return 0;
if(a == 2 || a == 3) return 1;
if(a%6 != 1 && a%6 != 5) return 0;
int sqrtA = sqrt(a);
for(int i = 5; i <= sqrtA; i += 6) {
if(!(a%i)|| !(a%(i+2))) return 0;
}
return 1;
}
如何理解记忆:
这个的理解过程就比较长了。【素数的判定-从暴力到高效】-C++ - 摸鱼酱 - 博客园 (cnblogs.com)
可以去博客园看一下这篇比较详细的博客,搬运一下。
看到这里,感谢观看,写了这么久,点个赞吧,嘿嘿嘿,下次见。
标签:return,gcd,公倍数,----,int,最大公约数,base,ans,模板 来源: https://blog.csdn.net/weixin_53729021/article/details/121109048
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。