10.1数论初步
来源:互联网 发布:热血传奇手游源码 编辑:程序博客网 时间:2024/05/22 04:47
10.1.1欧几里得算法和唯一分解定理
除法表达式
分析:
表达式的值一定可以写成A/B的形式:A是其中一些Xi的乘积,而B是其他数的乘积,而B是其他数的乘积。不难发现,X2必须放在分母位置,那其他数呢?
其他数均可以放在分子位置
接下来的问题就变成了:判断E是否为整数
第一种方法是利用前面介绍的高精度运算:k次乘法加一次除法,正确但是麻烦
第2种方法是利用唯一分解定理,把X2写成若干素数相乘的形式:
第3种方法是直接约分:每次约掉Xi和X2的最大公约数gcd(Xi,X2),则当且仅当约分结束后X2=1时E为整数,程序如下
int judge(int* X){ X[2]/=gcd(X[2],X[1]); for(int i=3;i<=k;i++) X[2]/=gcd(X[i],X[2]); return X[2]==1;}整个算法的时间效率取决于这里的gcd算法。
辗转相处法的关键在于如下恒等式:gcd(a,b)=gcd(b,a mod b).她和边界条件gcd(a,0)=a一起构成了下面的程序:
int gcd(int a,int b){ return b==0?a:gcd(b,a%b);}
利用gcd还可以求出两个整数a,b的最小公倍数lcm(a,b)
不难验证gcd(a,b)*lcm(a,b)=a*b,不过即使有了公式也不要大意,如果把lcm写成a*b/gcd(a,b),可能会出错,因为a*b会溢出,正确的写法是先除后乘,即a/gcd(a,b)*b
10.1.2Eratosthenes筛法
无平方因子的数。给出正整数n,m,区间[n,m]内的“无平方因子”的数有多少个?
分析:
对于这样的限制,直接枚举判断会超时:需要判断10***0个整数,所以需要用Eratosthenes筛法构造1~n的素数表
筛法的思想特别简单:对于不超过n的每个非负整数p,删除2p,3p,,,当处理完所有数之后,还没被删的就是素数,用VIS[i]表示i已经被删除
memset(vis,0,sizeof vis);for(int i=2;i<=n;i++) for(j=i*2;j<=n;j+=i) vis[j]=1;
10.1.3扩展欧几里得算法
直线上的点。求直线ax+by+c=0上有多少个整点,满足x [x1,x2],y [y1,y2]
分析:
在解决这个问题之前,首先学习欧几里得算法——找出一对整数(x,y),使得ax+by=gcd(a,b).注意,这里x和y不一定是正数,也可能是负数或者0.例如,gcd(6.15)=3,6*3-15*1=3,其中x=3,y=-1.这个方程还有其他解,如x=-2,y=1
下面是扩展欧几里得算法的程序
void gcd(int a,int b,int& d,int& x,int& y){ if(!b) { d=a;x=1;y=0; } else { gcd(b,a%b,d,y,x); y-=x*(a/b); }}用数学归纳法并不难证明算法的正确性,注意在递归调用时,x和y的顺序变了,而边界也是不难得出的:gcd(a,0)=1*a-0*0=a.这样,唯一需要记忆的是y-=x*(a/b),不懂也不要紧。
上面求出了ax+by=gcd(a,b)的一组解(x1,y1),?其他解?任取另外一组解(x2,y2),则ax1+by1=ax2+by2(他们都等于gcd(a,b)),变形得a(x1-x2)=b(y2-y1),近一些列的变形得出
他的任意数解都可以写成(x0+kB,y0-kA),A=a/gcd(a,b),B=b/gcd(a,b),k取任意整数
。。。。。。
10.1.4同与与模算术
可得下面公式
(a+b)mod n=((a mod n)+(b mod n))mod n
(a-b)mod n=((amodn)-(bmodn)+n)mod n
注意在减法中,由于a mod n可能小于b mod n,需要在结尾上+n,以及乘法过程中可能会溢出
int mul_mod(int a,int b,int n){ a%=n; b%=n; return (int)((long long)a*b%n);}分析:
首先,把大数写成自左向右的形式:1234=((1*10+2)*10+3)*10+4
scanf("%s%d",n,&m);int len=strlen(n);int ans=0;for(int i=0;i<len;i++) ans=(int)(((long long)ans*10+n[i]-'0')%m);printf("%d\n",ans);这个函数的时间复杂度为n,当n很大时速度不理想
下利用分治法
int pow_mod(int a,int n,int m){ if(n==0) return 1; int x=pow_mod(a,n/2,m); long long ans=(long long)x*x%m; if(n%2==1) ans=ans*a%m; return (int)ans;}//不是很懂
- 10.1数论初步
- 10.1数论初步
- 数论初步
- 数论初步
- 数论初步
- 数论初步
- 数论初步
- 数论初步
- 数论初步之欧几里德
- 数论初步(更新)
- 数论初步学习
- 数论初步(一)
- 算法竞赛入门10.1数论初步例题代码
- 数论初步之欧几里德算法
- 数论初步之扩展欧几里德
- 数论初步之快速幂取模
- 幂取模(数论初步) By ACReaper
- 练习9(数论初步)
- 解密ThreadLocal
- Java就业指导
- 接口测试
- WebRTC学习之ICE深入理解
- 使用Eigen库出现:error C2719: “cameraMatrix”: 具有 __declspec(align('16')) 的形参将不被对齐
- 10.1数论初步
- web接口测试工具Jmeter
- 设计模式
- Filter及FilterChain的使用详解
- 荔支源向各位拜年了
- 获取数组中的最大、最小值
- PHP-GD库
- JavaScript基础知识(三)
- CentOS 7 安装windows字体