算法模板

最大公约数 

//最大公约数 
int gcd(int a,int b)
{
	return b ? gcd(b,a%b) : a;
} 

 最小公倍数

//最小公倍数 
int lcm(int a,int b)
{
	return a*b/gcd(a,b); 
}

 素数打表

v//素数打表,埃拉托斯特尼筛法
const int maxn=1e6;
bool prime[maxn];
void isprime()
{
	memset(prime,0,sizeof(prime));
	prime[0]=prime[1]=1;
	for(int i=2;i*i

快速幂求余

//快速幂,(a^n)%mod
typedef long long ll;
ll pow_mod(ll a,ll n)
{
	ll ans=1;
	while(n)
	{
		if(n&1)
			ans=ans*a%mod;
		a=a*a%mod;
		n>>=1;
	}
	return ans;
} 

大数取模

//大数取模
int len=a.length();
int ans=0;
for(int i=0;i

逆元:b*c\equiv1(mod m)则c是b关于m的逆元 

费马小定理:a是不能被质数p整除的正整数,则有a^{p-1}\equiv 1(mod p) 可推出a*a^{p-2}\equiv1(mod p)即a关于p的逆元为a^{p-2}

a/b的模等于a*(b的逆元)的模

//逆元
long long quickpow(long long a,long long b)
{
	if(b<0)
		return 0;
	long long ret=1;
	a%=mod;
	while(b)
	{
		if(b&1)
			ret=ret*a%mod;
		a=a*a%mod;
		b>>=1; 
	}	
	return ret;
} 
long long inv(long long a)
{
	return quickpow(a,mod-2);
}

 扩展欧几里得求解逆元

a*x\equiv1(mod m)等价于a*x+m*y=1;可以用欧几里得求一组解,(x+m)mod m即为a的逆元

//扩展欧几里得求解逆元
int exgcd(int a,int b,int &x,int &y)
{
	if(b==0)
	{
		x=1;
		y=0;
		return a;
	}
	int r=exgcd(b,a%b,x,y)
	int t=y;
	y=x-(a/b)*y;
	x=t;
	return r;//最大公约数 
} 

1到n逆元表

//1到n逆元表,所有逆元都求反快
long long inv[maxn];
void prepare_inv(int n,int M)
{
	intv[1]=1;
	for(int i=2;i<=n;i++)
	{
		inv[i]=(long long )(M-M/i)*inv[M%i]%M;
	}
} 

算数基本定理:任何一个大于1的自然数n,如果n不为质数,那么n可以分解成有限个质数的乘积,并且在不计次数的情况下,这种分解方式是唯一的;60=2^{3}*3*5

补充:欧拉函数;

 φ(N)的值,我们可以通俗地理解为小于N且与N互质的数的个数(包含1).

对于一个正整数N的素数幂分解N=P1^q1*P2^q2*...*Pn^qn.

φ(N)=N*(1-1/P1)*(1-1/P2)*...*(1-1/Pn).

//算数基本定理
map prime_factor(int n)
{
	mapans;
	for(int i=2;i*i<=n;i++)
	{
		while(n%i==0)
		{
			ans[i]++;
			n/=i;
		}
	}
	if(n!=1)
		ans[n]=1;
	return ans;
} 

 二进制枚举

for(int i=0;i<1<>j&1);
		}	
		printf("\n");
	}

 线段相交

struct point
{
    double x,y;
};
bool inter(point a,point b,point c,point d)
{//判断线段ab和cd是否相交 
    if(min(a.x,b.x)>max(c.x,d.x)||min(a.y,b.y)>max(c.y,d.y)||min(c.x,d.x)>max(a.x,b.x)||min(c.y,d.y)>max(a.y,b.y))
        return 0;//快速排斥实验 
    double h,i,j,k;
    h=(b.x-a.x)*(c.y-a.y)-(b.y-a.y)*(c.x-a.x);
    i=(b.x-a.x)*(d.y-a.y)-(b.y-a.y)*(d.x-a.x);
    j=(d.x-c.x)*(a.y-c.y)-(d.y-c.y)*(a.x-c.x);
    k=(d.x-c.x)*(b.y-c.y)-(d.y-c.y)*(b.x-c.x);
    return h*i<=0&&j*k<=0;//跨立实验 
}

多边形面积:

struct point{
	int x,y;
}p;
int det(point a,point b)//叉乘 
{
	return a.x*b.y-a.y*b.x;
}
double area(point *ch,int m)//计算多边形的面积 ,凸多边形和非凸多边形均适用 
{
	double sum=0;
	for(int i=1;i

凸包;

struct point{
	int x,y;
}p[maxn],ch[maxn]; 
bool cmp(point a,point b)
{
	if(a.x==b.x)
		return a.y1&&det(ch[m-2],ch[m-1],p[i])>=0)
			m--;
		ch[m++]=p[i];
	}
	int k=m;
	for(int i=n-2;i>=0;i--)
	{
		while(m>k&&det(ch[m-2],ch[m-1],p[i])>=0)
			m--;
		ch[m++]=p[i];
	}
	if(n>1)
		m--;
	return m;//返回凸包边上树的个数 
}

 

 

你可能感兴趣的:(模板)