您的位置:首页 > 其它

数学问题的解题方法(模板)

2016-03-25 22:58 204 查看
辗转相除法:

1.最大公约数

int gcd(int a,int b){
if(b==0)
return a;
return gcd(b,a%b);
}


LL gcd(LL a, LL b)
{
return b == 0? a : gcd(b, a % b);
}

void ex_gcd(LL a, LL b, LL& d, LL& x, LL& y)
{
if(!b)
{
d = a;
x = 1;
y = 0;
}
else
{
ex_gcd(b, a % b, d, y, x);
y -= x * (a/b);
}
}


2.扩展欧几里德算法

ax+by=gcd(a,b)

int extgcd(int a,int b,int &x,int &y){
int d=a;
if(b!=0){
d=extgcd(b,a%b,y,x);
y-=(a/b)*x;
}
else{
x=1;
y=0;
}
return d;
}


有关素数的基础算法:

1.素数判定

//素性测试
bool prime(int n){
for(int i=2; i*i<=n; i++){
if(n%i==0)
return false;
}
return n!=1;  //1是例外
}

//约数枚举
vector<int> dis(int n){
vector<int> res;
for(int i=1; i*i<=n; i++){
if(n%i==0){
res.push_back(i);
if(i!=n/i)
res.push_back(n/i);
}
}
return res;
}

//整数分解
map<int,int> prime(int n){
for(int i=2; i*i<=n; i++){
while(n%i==0){
++res[i];
n/=i;
}
}
if(n!=1)
res
=1;
return res;
}


2.埃氏筛法

int prime[MAX_N]; //第i个素数
bool is_prime[MAX_N+1]   //is_prime[i]为true表示i是素数

//返回n以内素数的个数
int solve(int n){
int p=0;
for(int i=0; i<=n; i++)
is_prime[i]=true;
is_prime[0]=is_prime[1]=false;
for(int i=2; i<=n; i++){
if(is_prime[i]){
prime[p++]=i;
for(int j=2*i; j<=n; j+=i)
is_prime[i]=false;
}
}
return p;
}


3. 区间筛法

typedef long long ll;

bool is_prime[MAX_L];
bool is_prime_small[MAX_B];

//对区间[a,b)内的整数执行筛法.is_prime[i-a] = true  --  i是素数
void segment_sieve(ll a,ll b){
for(int i=0; (ll)i*i<b; i++)
is_prime_small[i]=true;
for(int i=0; i<b-a; i++)
is_prime[i]=true;
for(int i=2; (ll)i*i<b; i++){
if(is_prime_small[i]){
for(int j=2*i; (ll)j*j<b; j+=i)
is_prime_small[j]=false;  //筛[2,根号b)
for(ll j=max(2LL,(a+i-1)/i)*i; j<b; j+=i)
is_prime[j-a]=false; //筛[a,b)
}
}
}


模运算

LL qpow(LL x, LL k)
{
LL res = 1;
while(k)
{
if(k & 1) res = res * x % MOD;
x = x * x % MOD;
k >>= 1;
}
return res;
}

LL inv(LL a, LL x)
{
return qpow(a, x - 2);
}


凸包:

struct point
{
double x;
double y;
point (double x = 0, double y = 0):x(x), y(y)
{}
};
typedef point Vector;//向量
Vector operator + (Vector A, Vector B)//向量加法
{
return Vector(A.x + B.x, A.y + B.y);
}

Vector operator - (Vector A, Vector B)//向量减法
{
return Vector(A.x - B.x, A.y - B.y);
}

Vector operator * (Vector A, double p)//向量乘法
{
return Vector(A.x * p, A.y * p);
}

Vector operator / (Vector A, double p)//向量除法
{
return Vector(A.x / p, A.y / p);
}

int dcmp(double x)//精度控制
{
if(fabs(x) < eps) return 0;
else
return x < 0? -1 : 1;
}

bool operator == (const point& a, const point& b)//判断点相等
{
return dcmp(a.x - b.x) == 0 && dcmp(a.y - b.y) == 0;
}

double Dot(Vector A, Vector B)//向量点积,A*B,垂直为0
{
return A.x * B.x + A.y * B.y;
}

double Length(Vector A)//向量长度
{
return sqrt(Dot(A, A));
}

double Angle(Vector A, Vector B)//向量极角
{
return acos(Dot(A, B) / Length(A) / Length(B));
}

double Cross(Vector A, Vector B)//向量叉乘,AXB, 有向面积的两倍
{
return A.x * B.y - A.y * B.x;
}

double Area2(point A, point B, point C)//两向量组成的四边形的有向面积
{
return Cross(B - A, C - A);
}
Vector Rotate(Vector A, double rad)//向量A,逆时针旋转rad°, 极角形式
{
return Vector(A.x * cos(rad) - A.y * sin(rad), A.x * sin(rad) + A.y * cos(rad));
}

Vector Normal(Vector A)//A will not 0 Vector!, 求单位向量
{
double L = Length(A);
return Vector(A.x / L, A.y / L);
}

Vector GetLineIntersection(point P, Vector v, point Q, Vector w)//求两向量的交点(不求具体坐标)
{
Vector u = P - Q;
double t = Cross(w, u) / Cross(v, w);
return P + v * t;
}

double DistanceToLine(point P, point A, point B)// 点到直线的距离
{
Vector v1 = B - A, v2 = P - A;
return fabs(Cross(v1, v2)) / Length(v1);
}

double DistanceToSegment(point P, point A, point B)//点到线段的距离
{
if(A == B) return Length(P - A);
Vector v2 = P - A, v3 = P - B, v1 = B - A;
if(dcmp(Dot(v1, v2) < 0)) return Length(v2);
else if(dcmp(Dot(v1, v3)) > 0) return Length(v3);
else
return fabs(Cross(v1, v2)) / Length(v1);
}

point GetLineProjection(point P, point A, point B)//求点在直线上的投影
{
Vector v = B - A;
return A + v * (Dot(v, P - A) / Dot(v, v));
}

bool SegmentProperIntersection(point a1, point a2, point b1, point b2)//两线段是否相交
{
double c1 = Cross(a2 - a1, b1 - a1);
double c2 = Cross(a2 - a2, b2 - a1);
double c3 = Cross(b2 - b1, a1 - b1);
double c4 = Cross(b2 - b1, a2 - b1);
return dcmp(c1) * dcmp(c2) < 0 && dcmp(c3) * dcmp(c4) < 0;
}

bool OnSegment(point P, point a1, point a2)// 点是否在线段上
{
return dcmp(Cross(a1 - P, a2 - P)) == 0 && dcmp(Dot(a1 - P, a2 - P)) < 0;
}

double PolygonArea(point *p, int n)// 凸多边形(多边形)的有向面积
{
double area = 0;
for(int i = 1; i < n - 1;  i ++)
area += Cross(p[i] - p[0], p[i + 1] - p[0]);
return area / 2.0;
}


模板来自 : -> 萌哒哒~毅哥

<<挑战程序设计竞赛>>读后感......
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: