数学问题-排列组合

1.元素序列的排列与组合

组合序列:

void conbination(int n,int m,int a[],int b[],const int &M){ 
    for(int j=m;j<=n;j++){
        b[m-1]=a[j-1];
        if(m>1)
            conbination(j-1,m-1,a,b,M);
        else{
            for(int i=0;i<M;i++)
                printf("%d ",b[i]);
            printf("\n");
        }
    }
}

递归图解:

 

全排列:

void swap(int *p1,int *p2){
    int t=*p1;
    *p1=*p2;
    *p2=t;
}

void full_permutation(int a[],int t,int size){
    if(t==size){
        for(int i=0;i<size;i++)
            printf("%d ",a[i]);
        printf("\n");
    }
    else{
        for(int j=t;j<size;j++){
            swap(&a[j],&a[t]);
            full_permutation(a,t+1,size);//此处用到递归思想
            swap(&a[j],&a[t]);
        }
    }
}

将组合后的序列进行全排列,就得到了排列序列:

排列序列:

void permutation(int n,int m,int a[],int b[],const int &M){
    for(int j=m;j<=n;j++){
        b[m-1]=a[j-1];
        if(m>1)
            permutation(j-1,m-1,a,b,M);
        else{
            full_permutation(b,0,M);
        }
    }
} 

测试代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>

#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100
#define MAX 0x06FFFFFF
#define V vector<int>

using namespace std;

void conbination(int n,int m,int a[],int b[],const int &M){ 
    for(int j=m;j<=n;j++){
        b[m-1]=a[j-1];
        if(m>1)
            conbination(j-1,m-1,a,b,M);
        else{
            for(int i=0;i<M;i++)
                printf("%d ",b[i]);
            printf("\n");
        }
    }
}

void swap(int *p1,int *p2){
    int t=*p1;
    *p1=*p2;
    *p2=t;
}

void full_permutation(int a[],int t,int size){
    if(t==size){
        for(int i=0;i<size;i++)
            printf("%d ",a[i]);
        printf("\n");
    }
    else{
        for(int j=t;j<size;j++){
            swap(&a[j],&a[t]);
            full_permutation(a,t+1,size);//此处用到递归思想
            swap(&a[j],&a[t]);
        }
    }
}

void permutation(int n,int m,int a[],int b[],const int &M){
    for(int j=m;j<=n;j++){
        b[m-1]=a[j-1];
        if(m>1)
            permutation(j-1,m-1,a,b,M);
        else{
            full_permutation(b,0,M);
        }
    }
} 

int main(){
int n=5,m=3;
int a[n];int b[m];

for(int i=0;i<n;i++)

a[i]=i+1;

const int M=m;
puts("组合序列"); 
conbination(n,m,a,b,M);
puts("全排列");
full_permutation(a,0,n);
puts("排列序列");
permutation(n,m,a,b,M);
    return 0;
}
View Code

测试效果:

组合序列应用实例:

OJ链接:P1036 选数

AC代码:

#include <iostream>
#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map>
#include <numeric>


#define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 1010
#define MAX (1<<30)-1
#define V vector<int>

using namespace std;

int N,K; 
int num[LEN];
int res[LEN];
int ans=0;

bool isPrime(int x){
    if(x<2) return 0;
    for(int i=2;i<sqrt(x);i++){
        if(x%i==0) return 0;
    }
    return 1;
}

void conbination(int n,int m,int *a,int *b){//C(n,m)
    int i,j;
    for(i=m;i<=n;i++){
        res[m-1]=num[i-1];
        if(m>1)
            conbination(i-1,m-1,a,b);
        else{
            int sum=accumulate(res,res+K,0);
            if(isPrime(sum)){
//                FF(j,K) cout<<res[j]<<' ';
//                cout<<endl;
                ans++;
            }
        }
    }
}

int main(){
//    freopen("选数.txt","r",stdin);
    I("%d%d",&N,&K);
    int i;
    FF(i,N) cin>>num[i];
    conbination(N,K,num,res);
    cout<<ans<<endl;
    return 0;
}
View Code

 


 

2.排列组合公式

排列公式 P(n,m)=n!/(n-m)!

代码:

int P(int n,int m){
    int p=1;
    while(m){
        p*=n;
        n--;
        m--;
    }
    return p;
} 

代码理解:其实就是累乘,nx(n-1)x(n-2)x……x(m+1)x(m)

--------------------------------------------------

组合公式 C(n,m)=P(n,m)/m!=n!/[m!(n-m)!]

int C(int n,int m){
    int i,c=1;
    i=m;
    while(i){
        c*=n;
        n--;
        i--;
    }
    while(m){
        c/=m;
        m--;
    }
    return c;
}

代码理解:先求出P(n,m),再计算P(n,m)/m!

 

posted @ 2018-02-20 09:28  TQCAI  阅读(424)  评论(0编辑  收藏  举报