排列组合

2.3 生成gray

//生成reflected gray code

//每次调用gray取得下一个码

//000...000是第一个码,100...000是最后一个码

void gray(int n,int *code){

int t=0,i;

for (i=0;i<n;t+=code[i++]);

if (t&1)

for (n--;!code[n];n--);

code[n-1]=1-code[n-1];

}

2.4 置换(polya)

//求置换的循环节,polya原理

//perm[0..n-1]0..n-1的一个置换(排列)

//返回置换最小周期,num返回循环节个数

#define MAXN 1000

int gcd(int a,int b){

return b?gcd(b,a%b):a;

}

int polya(int* perm,int n,int& num){

int i,j,p,v[MAXN]={0},ret=1;

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

if (!v[i]){

for (num++,j=0,p=i;!v[p=perm[p]];j++)

v[p]=1;

ret*=j/gcd(ret,j);

}

return ret;

}

2.5 字典序全排列

//字典序全排列与序号的转换

int perm2num(int n,int *p){

int i,j,ret=0,k=1;

for (i=n-2;i>=0;k*=n-(i--))

for (j=i+1;j<n;j++)

if (p[j]<p[i])

ret+=k;

return ret;

}

void num2perm(int n,int *p,int t){

int i,j;

for (i=n-1;i>=0;i--)

p[i]=t%(n-i),t/=n-i;

for (i=n-1;i;i--)

for (j=i-1;j>=0;j--)

if (p[j]<=p[i])

p[i]++;

}

2.6 字典序组合

//字典序组合与序号的转换

//comb为组合数C(n,m),必要时换成大数,注意处理C(n,m)=0|n<m

int comb(int n,int m){

int ret=1,i;

m=m<(n-m)?m:(n-m);

for (i=n-m+1;i<=n;ret*=(i++));

for (i=1;i<=m;ret/=(i++));

return m<0?0:ret;

}

int comb2num(int n,int m,int *c){

int ret=comb(n,m),i;

for (i=0;i<m;i++)

ret-=comb(n-c[i],m-i);

return ret;

}

void num2comb(int n,int m,int* c,int t){

int i,j=1,k;

for (i=0;i<m;c[i++]=j++)

for (;t>(k=comb(n-j,m-i-1));t-=k,j++);

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值