1.错排公式
来源:当n个编号元素放在n个编号位置,元素编号与位置编号各不对应的方法数D(n)
推导:
第一步,把第n个元素放在一个位置,比如位置k,一共有n-1种方法;
第二步,放编号为k的元素,这时有两种情况:
(1)把它放到位置n,那么,剩下n-2个元素(第n个和第k个已经放好啦),就有D(n-2)种方法
(2)不把它放到位置n,这时,对于这n-1个元素(只有第n个是放好的),有D(n-1)种方法;
综上得到
D(n) = (n-1) [D(n-2) + D(n-1)]
特殊地,D(1) = 0, D(2) = 1.
应用例题:HDU-2048 神、上帝以及老天爷
2.组合公式
来源:从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。
公式:
性质:
代码:
long long int C(int n,int m)
{
long long x=1;
for(int i=1;i<=m;i++)
x=x*(n-i+1)/i;
return x;
}
3.GCD公式
公式:
应用例题:HDU-2685 I won’t tell you this is about number theory
关于这道题多写一段快速幂
int quickpow(int a,int b){
int r=1,base=a;
while(b){
if(b&1) r*=base; //这里b&1表示取b二进制的最末位
base*=base;
b>>=1; //这里>>=表示去掉b的二进制最后一个位并赋值给b
}
return r;
}
4.素数筛选
原理:从2~n,找到一个数(显然它是一个素数),就删去它的倍数
注意:仅仅需要i*i<=n即可(对于任何一个小于n的x,如果n不是x的倍数,那么n肯定也不是n/x的倍数)
int prime[500000];
void choseprime(int n)
{
prime[1]=prime[2]=0;
for(int i=2;i*i<=n;i++)
if(prime[i]==0)
for(int j=2*j;j<=n;j+=i)
prime[j]=1;
}
5.欧拉函数
定义:小于n的正整数中与n互质的的数的数目
性质:
1.积性函数:若m、n互质,
2.若n是质数p的k次幂,
思路:
设一个数 ,那么A的欧拉函数:
整理这个公式,得到如下公式:
做法:令temp=A,然后每找到一个A的质因子就从temp中除掉一个此因子然后再乘上(该因子-1)
long long int phi(long long int a)
{
long long int temp = a;
for(long long int i=2; i*i<=a; i++)
if(a%i==0)
{
while(!(a%i))
a/=i;
temp=temp/i*(i-1);
}
if(a!=1)
temp=temp/a*(a-1);
return temp;
}