首页 > 代码库 > 整理,模板

整理,模板

组合数学、
-排列组合数
----sum求
sum=sum*(m--)/i;
int c(int n,int m)//n下标,m上标
{
    int sum=1;
    for(int i=1;i<=m;i++)
        sum=sum*(n--)/i;
    return sum;
}
----二维数组递推(打表)
#define maxx 1000
int c[maxx+2][maxx+2];
void init()//递推打表
{
    memset(c,0,sizeof(c));
    c[0][0]=c[1][0]=c[1][1]=1;
    for(int i=2;i<maxx;i++)
    {
        c[i][i]=c[i][0]=1;
        for(int j=0;j<i;j++)
        {
            c[i][j]=(c[i-1][j-1]+c[i-1][j]);
        }
    }
}
---原始公式(单个)数字太大,用分子分母约分,优化
#define maxx 1000
int c[maxx+2][maxx+2];
void init()//递推打表
{
    if(m>n-m) 
        m=n-m; 
    int temp=n; 
    for(int i=1;i<=m;i++)//根据组合公式把原始的分子分母分别存在数组中 
    { 
        up[i]=temp--; 
        down[i]=i; 
    } 
    for(int i=1;i<=m;i++)//外层循环代表分母,对分母依次进行约分 
        for(int j=1;j<=m;j++) 
        { 
            temp=gcd(down[i],up[j]); 
            if(temp>1) 
            { 
                up[j]/=temp; 
                down[i]/=temp; 
            } 
            if(down[i]==1)//分母已经为1,退出,进行下一个分母的约分 
                break; 
        } 
    int sum=1; 
    for(int i=1;i<=m;i++) 
        sum=sum*up[i]/down[i]; 
    return sum;
}
-全排列模板
-----生成全排列函数
prev_permutation和next_permutation
int main ()
{
    int a[] = {1,2,3};
    do
    {
        cout<<a[0]<<" "<<a[1]<<" "<<a[2]<<endl;
    }while(next_permutation(a,a+3));// 后一个排列组合

    return 0;
}
区别prev_permutation //前一个排列组合
--母函数
模板---用的时候一般会变一下数,式子中等阶指数(xiayige)
--错排
错位排列的公式有
dn=n!(1-1/1!+1/2!-1/3!+...+(-1)^n*1/n!)
还有一个递推的形式
d[n]=(n-1)*(d[n-1]+d[n-2])
void D() 

    for(int i=2;i<=20;i++) 
        d[i]=(i-1)*(d[i-1]+d[i-2]); 

---卡特兰数
卡特兰数:
 1 通项公式:
h(n)=C(n,2n)/(n+1)=(2n)!/((n!)*(n+1)!)
 2递推公式:
h(n)=((4*n-2)/(n+1))*h(n-1); h(n)
       =h(0)*h(n-1)+h(1)*h(n-2)+...+h(n-1)*h(0).
3前几项为:h(0)=1,h(1)=1,h(2)=2,h(3)=5,h(4)=14,h(5)=42,......

欧拉函数
φ(x)=x(1-1/p1)(1-1/p2)(1-1/p3)(1-1/p4)…..(1-1/pn),
其中p1, p2……pn为x的所有质因数,x是不为0的整数。φ(1)=1
求单个(公式地推)
int phi(int n)//求phi(n)
{
    int m=(int)sqrt(n+0.5);
    int ans=n;
    for(int i=2;i<=m;i++)
        if(n%i==0)
        {
            ans=ans/i*(i-1);
            while(n%i==0)
                n/=i;
        }
    if(n>1)
        ans=ans/n*(n-1);
    return ans;
}
打表(筛法)
#define maxn 32768
int phi[maxn];
void phi_table(int n)
{
    for(int i=2;i<=n;i++)
        phi[i]=0;
    phi[1]=1;
    for(int i=2;i<=n;i++)
        if(!phi[i])
        for(int j=i;j<=n;j+=i)
        {
            if(!phi[j])
                phi[j]=j;
            phi[j]=phi[j]/i*(i-1);
        }
}
背包
01
c[i][m]=max{c[i-1][m],c[i-1][m-w[i]]+p[i]}

这个方程非常重要,基本上所有跟背包相关的问题的方程都是由它衍生出来的。所以有必要将它详细解释一下:“将前i件物品放入重量为m的背包中”这个子问题,若只考虑第i件物品的策略(放或不放),那么就可以转化为一个只牵扯前i-1件物品的问题。如果不放第i件物品,那么问题就转化为“前i-1件物品放入容量为v的背包中”,价值为c[i-1][m];如果放第i件物品,那么问题就转化为“前i-1件物品放入剩下的重量为m-w[i]的背包中”,此时能获得的最大价值就是c[i-1][m-w[i]]再加上通过放入第i件物品获得的价值p[i]。