基础篇——数论基础
2016-01-20 15:09
197 查看
数论基础主要有三点。1.最大公约数。2.素数问题。3.快速幂取模。
一:最大公约数
正常的思路,求最大公约数都是从2开始到n-1求最大能整除的数即为最大公约数。但这样算的时间为o(n),相当耗时。故在求最大公约数时,提出了辗转相除法。
现有a,b两个数,a除以b的商和余数分别是p和q,所以a=b*p+q,所以gcd( b , q )整除a,b故而整除gcd( a ,b )。反之因为q=a-b*q,可得gcd( a,b )整除gcd( b,q )。因此gcd( a,b )=gcd( b,a%b )。由于gcd的第二个参数是不断减小的,最终会得到gcd( a,b )=gcd( c,0 )。0和c的最大公约数是c,故c为a和b的最大公约数。
辗转相除法是一个递归的算法,其时间复杂度为o(log max(a,b)),大多数情况下够用了。
二:素数问题
素数也称质数,指除了1和其本身外再无别的因数的数。一般判定一个数是否是素数,通常我们会从2到√n遍历,若有能整除n的数则说明n不是素数。算法时间为o(√n),看起爱还可以,但若是给你一串数求其中素数的个数,那么这种算法就显得low了。有人机智的提出了素数筛。
将2到n之间的整数记录下来,其中最小的素数是2,将表中2的倍数全部不划去,表中剩余的最小的数字为3,再将3的倍数全划去,以此类推,就能找到所有的素数。这样做的时间复杂度只有o(nlog log n)。
上述代码是求从1到n的素数,若是求[a,b)范位内的素数怎么求呢?
原理也是一样,开一个[1,b)的is_prime[ ]数组,按照相同的素数筛处理,最后找在[a,b)范围内的素数即可。
三:快速幂取模
数论问题经常遇见非常大的数,例如 X ^ 22,通常的思路是采用for循环,但当数很大时运算效率会很低。
采用快速幂算法可以将X^22拆为X^16 , X^4和X^2。时间复杂度直降至o(log n)。
一:最大公约数
正常的思路,求最大公约数都是从2开始到n-1求最大能整除的数即为最大公约数。但这样算的时间为o(n),相当耗时。故在求最大公约数时,提出了辗转相除法。
现有a,b两个数,a除以b的商和余数分别是p和q,所以a=b*p+q,所以gcd( b , q )整除a,b故而整除gcd( a ,b )。反之因为q=a-b*q,可得gcd( a,b )整除gcd( b,q )。因此gcd( a,b )=gcd( b,a%b )。由于gcd的第二个参数是不断减小的,最终会得到gcd( a,b )=gcd( c,0 )。0和c的最大公约数是c,故c为a和b的最大公约数。
辗转相除法是一个递归的算法,其时间复杂度为o(log max(a,b)),大多数情况下够用了。
int gcd(int a,int b) { if(b==0) return a; gcd(b,a%b); }
二:素数问题
素数也称质数,指除了1和其本身外再无别的因数的数。一般判定一个数是否是素数,通常我们会从2到√n遍历,若有能整除n的数则说明n不是素数。算法时间为o(√n),看起爱还可以,但若是给你一串数求其中素数的个数,那么这种算法就显得low了。有人机智的提出了素数筛。
将2到n之间的整数记录下来,其中最小的素数是2,将表中2的倍数全部不划去,表中剩余的最小的数字为3,再将3的倍数全划去,以此类推,就能找到所有的素数。这样做的时间复杂度只有o(nlog log n)。
int prime[MAXN+1]; //用于记录每个素数 bool is_prime[MAXN+1];//值为true即为素数 int sieve(int n) { int p=0; for(int i=1;i<=n;i++) is_prime[i]=true; is_prime[0]=false; is_prime[1]=false; for(int i=2;i<=n;i++) { if(is_prime[i]) { prime[p++]=i; //将素数记录到prime中 for(int j=2*i;j<=n;j+=i) //素数i的倍数的is_prime值全部改为false; is_prime[j]=false; } } return p; }
上述代码是求从1到n的素数,若是求[a,b)范位内的素数怎么求呢?
原理也是一样,开一个[1,b)的is_prime[ ]数组,按照相同的素数筛处理,最后找在[a,b)范围内的素数即可。
三:快速幂取模
数论问题经常遇见非常大的数,例如 X ^ 22,通常的思路是采用for循环,但当数很大时运算效率会很低。
采用快速幂算法可以将X^22拆为X^16 , X^4和X^2。时间复杂度直降至o(log n)。
typedef long long ll; ll quick_pow(ll x,ll n,ll mod) { ll ans=1; while(n>0) { if(n&1) ans=ans*x%mod; x=x*x%mod; n>>=1; } return ans; }
相关文章推荐
- 项目从mysql移植到SQL sqlserver问题汇总
- jeecg 弹出框 点击按钮回调父页面 返回值
- FreeChart柱状图中如何取消柱子的倒影
- Python入门
- 文件操作
- MD5加密
- NSIndexPath的初始化方法
- JAVA NIO 服务器(三)
- Leetcode@Jump Game II
- hadoop-运行hadoop jar hadoop-examples-1.2.1.jar wordcount /wc/input/ /wc/output/
- Pods的使用
- Android Studio导入(import)工程时常见错误
- 重启,关机命令
- JAVA web学习路线
- GestureDetector 和SimpleOnGestureListener的使用和解释
- OpenSSH客户端漏洞:CVE-2016-0777和CVE-2016-0778
- Word中在校对中取消自动更正- 句首字母大写
- Android中为何会显示隐藏的UI?
- pdf.js使用和JS实现嵌套Iframe页面F11全屏效果
- apache域名重定向301跳转 .htaccess的写法