算法组合数
⑴ 排列组合公式及排列组合算法
排列组合公式
排列组合公式/排列组合计算公式
公式P是指排列,从N个元素取M个进行排列。
公式C是指组合,从N个元素取M个进行组合,不进行排列。
N-元素的总个数
M参与选择的元素个数
!-阶乘,如9!=9*8*7*6*5*4*3*2*1
从N到数M个,表达式应该为n*(n-1)*(n-2)..(n-m+1);
因为从n到(n-m+1)个数为n-(n-m+1)=m
举例:
Q1: 有从1到9共计9个号码球,请问,可以组成多少个三位数?
A1: 123和213是两个不同的排列数。即对排列顺序有要求的,既属于“排列P”计算范畴。
上问题中,任何一个号码只能用一次,显然不会出现988,997之类的组合,我们可以这么看,百位数有9种可能,十位数则应该有9-1种可能,个位数则应该只有9-1-1种可能,最终共有9*8*7个三位数。计算公式=P(3,9)=9*8*7,(从9倒数3个的乘积)
Q2:有从1到9共计9个号码球,请问,如果三个一组,代表“三国联盟”,可以组合成多少个“三国联盟”?
A2:213组合和312组合,代表同一个组合,只要有三个号码球在一起即可。即不要求顺序的,属于“组合C”计算范畴。
上问题中,将所有的包括排列数的个数去除掉属于重复的个数即为最终组合数C(3,9)=9*8*7/3*2*1
⑵ 数学的排列组合算法加公式
不能重复的c(6,4) c(6,5) 1,2,3......,n n个数中 任取m个组合 c(n,m) 能重复的 6^4 6^5 1,2,3,。。。。n,n个数中,取m个组合(可重复) n^m 追问: c(n,m),读作什么?把1-6取4位带进去怎么算,可以教我吗?50分感激不尽 回答: 这个是组合数 从n个元素里面取m个元素的组合数 比如c(6,4)=(6*5*4*3)/(1*2*3*4) c(n,m)=[n*(n-1)*.........*(n-m+1)]/(1*2*......*m) 分子从n开始往下取 一直取m个连续的自然数相乘 分母从1取到m m个连续自然数相乘 追问: c(n,m)=[n*(n-1)*.........*(n-m+1)]/(1*2*......*m) 后面的/(1*2*......*m)是要除的么? 这个怎么求的? 回答: 你题目说的不是很清楚 如果说要是组成数字 就不需要除以下面的(排列) 若只是取出来 不要求构成数字 则要除(组合) 补充: 只算组合 不要求构成数字 你的做法是对的 补充: 不可重复 15组 可重复 6^4=1296组 补充: 估计你的题目是要求构成数字的 不可重复的就是 6*5*4*3=360种 可重复的还是1296种 补充: 你一直都没说 是否要求构成数字 取4个数字出来 是要构成一个4位数吗? 如果是 则是360种 不是 则是15种 补充: 这是你自己想的题目吧 原题绝对不会说这样的话 补充: 排列组合你没学 这些一下你也搞不懂的 打个比方,从1,2,3中取2个数字 则有3种取法 {1,2},{1,3),{2,3} 如果你要是说取2个数字构成2位数 则有6种12,21,13,31,23,32 你对照公式看下 追问: 就是6位取4位构成4位数就有360种,那么15种又是哪里来的? 回答: 晕了 我已经说的很清楚了啊 例子都列出来了 15种是取出来不进行排列 360是还要进去排列组成4位数 补充: 你要是自学排列组合 还是先把定义搞清楚吧 再说 你出的这个题目本身说的就模棱两可得 我一直在问你是否要求构成四位数 360和15得区别就在于这点 追问: 我终于懂了,在你们精心辅导下,我终于懂了,其实我对这些一窍不通,根本都没学!谢谢你们悬赏最高!
⑶ 怎样求大组合数(取模)(ACM算法)
这种题目然做过的,
意思比较简单,就由 m 个共 0 和 n 个 1 组成一个串,但从左到右要1出现的次数不少于0出现的次数。
由大牛的算法: 结果就是 C(m+n, n) - C(m+n, m-1) 再取模,我们可以对式子化简一下就是:
(n+m)!*
(n-m+1) / ((m)!* (n+1)!)
再取模,但由于组合数很大,直接用大数乘除就会超时了,看了别人的报告才知道原来可以用素数化简快速求模的, n! = 2^p[i] *
3^p[i] * 5^p[i]*...... 再求模就可以很快了~(^ = ^)~。。。
#include<iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
#define M 2000005
#define mm 20100501
bool sig[M];
int prime[150000], p[150000], len; // prime 记录素数, p 记录素数的幂 len 记录长度
void getprime() // 筛法找素数
{
int i,j,k=0;
prime[k++] = 2;
for(i=3; i<=M; i+=2)
{
if( !sig[i] )
{
prime[k++] = i;
for(j=i; j<=M; j+=i)
sig[j] = 1;
}
}
}
void get(int k, int s) // K! 的素数分解, S为指数的加减(分母,分子)
{
int i, mid;
for(i=0; prime[i]<=k && prime[i]; i++)
{
mid = k;
while(mid)
{
if(s)
p[i] += mid/prime[i];
else
p[i] -= mid/prime[i];
mid /= prime[i];
}
}
if(len < i)
len = i;
}
__int64 cal() // 计算结果 (prime[i...]^p[i...]) % mm
{
__int64 i,ans = 1;
for(i=0; i<=len; i++)
{
if( p[i] )
{
__int64 t = prime[i], b = p[i], ret = 1;
while(b) //计算 (t^b) % mm
{
if(b%2) ret *= t %mm;
t = t*t%mm;
b /= 2;
}
ans = ( ans*ret ) % mm;
}
}
return ans;
}
int main()
{
int t,m,n,i,mid;
__int64 ans;
getprime();
cin>>t;
while(t--)
{
cin>>n>>m;
len = 0;
memset(p, 0, sizeof(p));
mid = n-m+1; //先前要把 n-m+1 的因子加进 P 中去才能使 (m+n)! / ((m)!*(n+1)!) 整除
for(i=0; mid>1; i++)
{
if( mid%prime[i] == 0)
{
while(mid%prime[i]==0)
{
p[i] += 1;
mid /= prime[i];
}
}
}
get(m+n, 1);
get(m, 0);
get(n+1, 0);
ans = cal();
printf("%I64d\n", ans);
}
return 0;
}
可以用素数分解法,
先求出上面和下面的素数表示,然后约分后,再用求幂公式
⑷ 求排列组合算法,比如C62(6在下,2在上),麻烦详细一点,高中的知识还给老师了,汗
C62(6在下,2在上)计算方法如下:
⑸ c语言组合数算法不用递归怎么做
不用递归则可以用 公式的呀,从n个元素中选取m个(n>=m)的组合数,公式如下。
C(n, m) = n!/(m! * (n-m)!)
而m!和(n-m)!两者中的较大一个可以和n!的前若干项约分掉,我们不妨设n-m > m,则(n-m)!可以被约掉,只要求m!和 (n-m+1)*...*n即可。然后将这两个连乘积相除,即为组合数。
程序可如下:
#include <stdio.h>
void main( )
{
int n, m, max, min, i, s = 1, r = 1;
scanf("%d%d", &n, &m);
max = (m > (n-m) ? m : (n - m));
min = n - max;
for(i = 1; i <= min; i++)
r *= i, s *= (max + i);
printf("C(%d,%d) = %d ", n, m, s / r); /*max的阶乘可以约掉,所以不必求*/
}
运行结果:
⑹ 能不能讲给我关于排列,组合的公式怎么算法
zfjsdc
翟玉兰 发表于 2007-3-3 15:14:00
排列与组合的概念与计算公式
1.排列及计算公式
从n个不同元素中,任取m(m≤n)个元素按照一定的顺序排成一列,叫做从n个不同元素中取出m个元素的一个排列;从n个不同元素中取出m(m≤n)个元素的所有排列的个数,叫做从n个不同元素中取出m个元素的排列数,用符号
p(n,m)表示.
p(n,m)=n(n-1)(n-2)……(n-m+1)= n!/(n-m)!(规定0!=1).
2.组合及计算公式
从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数.用符号
c(n,m) 表示.
c(n,m)=p(n,m)/m!=n!/((n-m)!*m!);c(n,m)=c(n,n-m);
3.其他排列与组合公式
从n个元素中取出r个元素的循环排列数=p(n,r)/r=n!/r(n-r)!.
n个元素被分成k类,每类的个数分别是n1,n2,...nk这n个元素的全排列数为
n!/(n1!*n2!*...*nk!).
k类元素,每类的个数无限,从中取出m个元素的组合数为c(m+k-1,m).
⑺ 排列组合公式算法是什么
排列组合是组合学最基本的概念公式,从n个中取m个排一下,有n(n-1)(n-2)…(n-m+1)种,即n/(n-m)。排列组合计算公式从n个不同元素中取出m(m≤n)个元素的所有排列的个数。
从n个不同元素中,任取m(m≤n)个元素并成一组,叫做从n个不同元素中取出m个元素的一个组合;从n个不同元素中取出m(m≤n)个元素的所有组合的个数,叫做从n个不同元素中取出m个元素的组合数。用符号 C(n,m) 表示。
根据组合学研究与发展的现状,它可以分为如下五个分支:经典组合学、组合设计、组合序、图与超图和组合多面形与最优化。
由于组合学所涉及的范围触及到几乎所有数学分支,也许和数学本身一样不大可能建立一种统一的理论。然而,如何在上述的五个分支的基础上建立一些统一的理论,或者从组合学中独立出来形成数学的一些新分支将是对21世纪数学家们提出的一个新的挑战。
⑻ 数字排列组合算法
例子: C1,3=(3*2*1)/(3-1)!*1!
组合:C7,9=36 组
排列:A7,9=181440 组
⑼ 排列组合中A和C的算法怎么算的,查了百度都不会,求详细点的谢谢(高中)
排列数 A(n,m) ----------即 字母A右下角n 右上角m,表示n取m的排列数
A(n,m)=n!/(n-m)!=n*(n-1)*(n-2)*……*(n-m+1)
A(n,m)等于从n 开始连续递减的 m 个自然数的积
n取m的排列数 A(n,m) 等于从n 开始连续递减的 m 个自然数的积
例: A(7,3)=7*6*5=210
组合数 C(n,m) ----------即 字母C右下角n 右上角m,表示n取m的排列数
C(n,m)=n!/(m!*(n-m)!)=n*(n-1)*(n-2)*……*(n-m+1)/(1*2*3*……*m)
C(n,m)等于(从n 开始连续递减的 m 个自然数的积)除以(从1开始连续递增的 m 个自然数的积)
n选m的组合数 C(n,m) 等于(从n 开始连续递减的 m 个自然数的积)除以(从1开始连续递增的 m 个自然数的积)
例: C(7,3)=7*6*5/(1*2*3)=35
⑽ 组合算法:从m个数中选n个数的所有组合
#include <iostream.h>
int combine(int a[], int n, int m)
{
m = m > n ? n : m;
int* order = new int[m+1];
for(int i=0; i<=m; i++)
order[i] = i-1;
int count = 0;
int k = m;
bool flag = true;
while(order[0] == -1)
{
if(flag)
{
for(i=1; i<=m; i++)
cout << a[order[i]] << " ";
cout << endl;
count++;
flag = false;
}
order[k]++;
if(order[k] == n)
{
order[k--] = 0;
continue;
}
if(k < m)
{
order[++k] = order[k-1];
continue;
}
if(k == m)
flag = true;
}
delete[] order;
return count;
}
int main()
{
const int M = 4;
const int N = 3;
int a[M];
int b[N];
for(int i=0;i<M;i++)
a[i] = i+1;
combine(a,M,N);
return 0;
}