参考:NENU CS ACM模板made by tiankonguse 2.13 GCD
快速gcd:
位操作没学,真心不懂二进制,还是得学啊
code:

1 int kgcd(){ 2 if(!a || !b) 3 return a?a:b; 4 if(!(a&1) && !(b&1)) 5 return kgcd(a>>1,b>>1)<<1; 6 if(!(b&1)) 7 return kgcd(a,b>>1); 8 if(!(a&1)) 9 return kgcd(a>>1,b); 10 return kgcd(b,a%b); 11 }
在说fgcd之前先说一下fmod函数吧
fmod:
原型:extern float fmod(float x, float y);
头文件:#include <math.h>
功能:计算x/y的余数
说明:返回x-n*y,使用codeblocks编译符号同x。n=[x/y](向离开零的方向取整)
举例:

1 int main(){ 2 double x,y; 3 x=24.238; 4 y=5; 5 printf("%lf ",fmod(x,y)); 6 }
运行结果是 4.238
这个函数还可以取得某个数的小数点后的部分。如:
fload f = 1.234;
fmod(f,(int)f)即可得到小数点后的部分
fgcd:(实数的gcd)
模板:
#define eps 1e-8 double fgcd(double a,double b){ if(b > -eps && b < eps){ return a; } else{ return fgcd(b,fmod(a,b)); }
举例:
Apr 30,2014 codeforces
C. Ancient Berland Circus
题目大意:给出3个点,求最小面积的正多边形,使得这3个点为正多边形的顶点。
算法分析:
根据正多边形的性质,正多边形的每个顶点都在其外接圆上。
已知3个点,可以根据海伦公式求出三角形的面积S。然后根据正弦定理求出外接圆的半径R=abc/(4S),根据余弦定理求出三个圆心角。
求出三个圆心角的最大公约数A,则正多边形由2*pi/A个小三角形组成。
根据正弦定理求出每个小三角形的面积S0,则答案即为S0*2*pi/A。
Code:

1 #include <cstdio> 2 #include <cmath> 3 4 using namespace std; 5 6 const double pi=acos(-1),eps=1e-4; 7 8 double x[3],y[3],a,b,c,A,B,C,p,S,R,alpha,S0,n; 9 10 double fgcd(double a,double b){ 11 if (fabs(b)<eps) return a; 12 return fgcd(b,fmod(a,b)); 13 } 14 15 int main(){ 16 for (int i=0;i<3;++i) scanf("%lf%lf",&x[i],&y[i]); 17 a=sqrt((x[0]-x[1])*(x[0]-x[1])+(y[0]-y[1])*(y[0]-y[1])); 18 b=sqrt((x[0]-x[2])*(x[0]-x[2])+(y[0]-y[2])*(y[0]-y[2])); 19 c=sqrt((x[1]-x[2])*(x[1]-x[2])+(y[1]-y[2])*(y[1]-y[2])); 20 A=2*acos((b*b+c*c-a*a)/2/b/c); 21 B=2*acos((a*a+c*c-b*b)/2/a/c); 22 C=2*pi-A-B; 23 p=(a+b+c)/2; 24 S=sqrt(p*(p-a)*(p-b)*(p-c)); 25 R=a*b*c/4/S; 26 alpha=fgcd(fgcd(A,B),C); 27 n=2*pi/alpha; 28 S0=R*R*sin(alpha)/2; 29 printf("%0.7lf ",n*S0); 30 return 0; 31 }
关于GCD的一些结论
1.有两个数p,q,gcd(p,q) = 1,则最大无法表示成px+qy(x >= 0 ,y >= 0)的数是pq-q-p.
2.区间内与n的gcd不小于m的数
输入m,n,求1-n之间中gcd(x,n) >= m 的x的个数。
找出N的所有大于等于M的因子(x1,x2,x3......xi),然后设k = N/xi.
下面只需找出小于k且与k互质的数。
因为:设y小于k且与k互质,那么gcd(y*xi,k*xi) = xi,(xi为k的因子,且xi大于等于M)。