康拓排序各种求法

全排序与康拓展开

n=3

全排列:

123

132

213

231

312

321

每个数列由1~n组成,且出现一次。

对于第一个位置,有n种选择,对于第二个位置,有(n-1)种选择,…,对于最后一个位置,有1种选择,所有共有n!种排序方法。

数列从小到大排序(或从大到小排序,或不排序))。

数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

而num:0~n!-1,a[k]<=k-1。

证明:

若x[n]_x[n-1]_…_x[k+1]_(min)的起始编号为x,

则x[n]_x[n-1]_…_x[k+1]_x[k]_(min)的起始编号为x+a[k]*(k-1)!,即某一个x[k]在原来的基础上加上a[k]*(k-1)!。

注意0!=1。因为定义C(x,y)=x!/(x-y)!/y!,而C(x,0)=x!/x!/0!=1,所以定义0!=1。

求全排序:

I.

dfs1,时间效率高,但数列并没有排序。

#include <iostream>

#define maxn 15

using namespace std;

//每一位的确定:还未使用的数 依次被选择(swap(a[pos],a[i]);  //以a[i]作为第pos位)

//所以数列不会产生重复

//数列没有排序!

//第pos位有1次未交换位置,(n-pos)次交换位置

//而与第pos位中的某个数延展得到的数有(n-pos)!个

//交换两数和交换回来需要6次操作

//(n-1)!*(n-1)+(n-2)!*(n-2)+…+1!*1=n!-1

//O(6*(n!-1))=O(6n!),时间复杂度很低,创建全排序效率很高!

long a[maxn+1],n;

void swap(long &a,long &b)

{

long temp;

temp=a;

a=b;

b=temp;

}

void dfs(long pos)

{

long i;

if (pos==n)

{

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

cout<<a[i]<<" ";

cout<<endl;

}

else

{

dfs(pos+1);

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

{

swap(a[pos],a[i]);  //以a[i]作为第pos位

dfs(pos+1);

swap(a[pos],a[i]);

}

}

}

int main()

{

long i;

cin>>n;

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

a[i]=i;

dfs(1);

return 0;

}

II.

dfs2,时间复杂度高

#include <iostream>

#define maxn 15

using namespace std;

//dfs:要是哪个数未被使用,就使用该数

//由于是按从小到大的顺序判断,所以数列也是从小到大排序

//dfs执行完后要改变为原来的状态(回溯):vis[i]=true;(标记该数未被使用)

//dfs时间复杂度较高

long n,a[maxn+1];

bool vis[maxn+1];

void dfs(long pos)

{

long i;

if (pos==n+1)

{

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

cout<<a[i]<<" ";

cout<<endl;

}

else

{

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

if (vis[i])

{

vis[i]=false;

a[pos]=i;

dfs(pos+1);

vis[i]=true;

}

}

}

int main()

{

long i;

cin>>n;

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

{

vis[i]=true;

a[i]=i;

}

dfs(1);

return 0;

}

III.

小到大排序,由第k个数推出第(k+1)个数

#include <stdio.h>

#include <stdlib.h>

#define maxn 15

//编号为k的数列通过一系列操作改变为编号为k+1的数列

int main()

{

long j,k,n,temp,x,y,a[maxn+1];

long long i,s;

scanf("%ld",&n);

//posibility

s=1;

for (i=2;i<=n;i++)

s=s*i;

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

a[i]=i;

for (k=1;k<=n;k++)

printf("%ld ",a[k]);

printf("\n");

for (i=1;i<s;i++)

{

//4 8 7 6 5 3 2 1

//5 8 7 6 4 3 2 1

//5 1 2 3 4 6 7 8

//从尾到头,找到第一个下降的a[j]

for (j=n-1;j>=1;j--)

if (a[j]<a[j+1])

break;

//a[j]:从尾到a[j],找到第一个比a[j]大的数a[k]

for (k=n;k>j;k--)

if (a[k]>a[j])

break;

//交换a[j]和a[k]的值

temp=a[j];

a[j]=a[k];

a[k]=temp;

//数组:j+1~n reverse

x=j+1;

y=n;

while (x<y)

{

temp=a[x];

a[x]=a[y];

a[y]=temp;

x++;

y--;

}

for (k=1;k<=n;k++)

printf("%ld ",a[k]);

printf("\n");

}

return 0;

}

IV.

康拓展开,通过数的编号逆推出数

#include <iostream>

#define maxn 15

using namespace std;

//数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

//该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

//a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

//num:0~n!-1 a[k]<=k-1

//时间复杂度:

//寻找数列:x[n]_x[n-1]_…_x[1]

//1~x[n];1~x[n-1];…;1~x[1],总x[n]+x[n-1]+…+x[1]=1+2+…+n=n*(n+1)/2

//数列共有n!个,所以O(n*(n+1)/2*n!),这是个大概值

int main()

{

long n,value[maxn+1],i,j,k,num,pos;

bool vis[maxn+1];

cin>>n;

value[1]=1;

value[2]=1;

for (i=2;i<=n;i++)

value[i+1]=value[i]*i;

for (i=0;i<value[n+1];i++)

{

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

vis[j]=false;

num=i;

for (j=n;j>=1;j--)

{

pos=num/value[j];

num-=pos*value[j];

//assume TTFTTTFFT

k=0;

while (pos>=0)

{

pos--;

k++;

while (vis[k])

k++;

}

vis[k]=true;

cout<<k<<" ";

}

cout<<endl;

}

return 0;

}

修改后速度提高:

#include <iostream>

#define maxn 15

using namespace std;

//数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

//该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

//a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

//num:0~n!-1 a[k]<=k-1

//时间复杂度:

//寻找数列:x[n]_x[n-1]_…_x[1]

//找x[k]次需要a[k]次,寻找一个数列需要a[n]+a[n-1]+…+a[1]次操作

//a[k]:0~k-1出现概率相同,平均值为(k-1)/2

//所以a[n],a[n-1],…,a[1]的平均值为(n-1)/2,(n-2)/2,…,0

//数列共有n!个,所以O(((n-1)/2+(n-2)/2+…+0)*n!)=O((n-1)*n/4*n!)

//这个值是被低估的,但比上个方法快

int main()

{

long n,value[maxn+1],i,j,num,pos,next[maxn+1],s,head;

cin>>n;

value[1]=1;

value[2]=1;

for (i=2;i<=n;i++)

value[i+1]=value[i]*i;

for (i=0;i<value[n+1];i++)

{

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

next[j]=j+1;

head=1;

num=i;

for (j=n;j>=1;j--)

{

pos=num/value[j];

num-=pos*value[j];

//assume TTFTTTFFT

if (pos==0)

{

cout<<head<<" ";

head=next[head];

}

else

{

s=head;

while (pos>1)

{

s=next[s];

pos--;

}

cout<<next[s]<<" ";

next[s]=next[next[s]];

}

}

cout<<endl;

}

return 0;

}

康拓展开求编号

s[1],s[2],…,s[n]都不相同,且{s[1],s[2],…,s[n]}={1,2,…,n}

   X=(s[1],s[2],…,s[n])

Number(X)=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[1]*0!

a[i]:数s[i]比s[i+1]~s[n]大的个数或者s[i]-1 减去s[i]比s[1]~s[i-1]大的数目

(因为n个数从1~n且都不相同,比s[i]小的数有s[i]-1个)

如X=2413

Number(2413)=1*3!+2*2!+0*1!+0*0!=10

求一个数X的编号(从小到大排序,最小数的编号为0)

Code:

#include <stdio.h>

#include <stdlib.h>

#define maxn 15

int main()

{

long n,i,j,x[maxn+1],value[maxn+1],pos,ans=0;

scanf("%ld",&n);

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

scanf("%ld",&x[i]);

//value[1]=1;

value[2]=1;

for (i=2;i<n;i++)

value[i+1]=value[i]*i;

//不用考虑最后1位,最后一位对应的值为0

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

{

pos=0;

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

if (x[i]>x[j])

pos++;

ans+=pos*value[n+1-i];

}

printf("%ld\n",ans);

return 0;

}

Code:(高精度)

#include <iostream>

#include <memory.h>

using namespace std;

long max(long a,long b)

{

if (a>b)

return a;

else

return b;

}

int main()

{

long n,i,j,s[100],value[100][100],len[100],g,ans[100],lenans,c[100],lenc;

cin>>n;

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

cin>>s[i];

value[0][1]=0;

len[1]=1;

value[1][1]=1;

len[1]=1;

for (j=2;j<n;j++)

{

value[j][1]=0;

for (i=1;i<=len[j-1];i++)

{

value[j][i]+=value[j-1][i]*j;

if (value[j][i]>=10000)

{

value[j][i+1]=value[j][i]/10000;

value[j][i]=value[j][i]%10000;

}

else

value[j][i+1]=0;

}

if (value[j][i]==0)

len[j]=len[j-1];

else

len[j]=len[j-1]+1;

}

/*

value[0]=0;

value[1]=1;

for (i=2;i<n;i++)

value[i]=value[i-1]*i;

*/

lenans=1;

memset(ans,0,sizeof(ans));

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

{

g=0;

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

if (s[i]>s[j])

g++;

//ans+=g*value[n-i];

c[1]=0;

for (j=1;j<=len[n-i];j++)

{

c[j]+=g*value[n-i][j];

if (c[j]>=10000)

{

c[j+1]=c[j]/10000;

c[j]=c[j]%10000;

}

else

c[j+1]=0;

}

if (c[j]==0)

lenc=j-1;

else

lenc=j;

lenans=max(lenans,lenc);

for (j=1;j<=lenans;j++)

{

ans[j]+=c[j];

if (ans[j]>=10000)

{

ans[j+1]++;

ans[j]-=10000;

}

}

if (ans[j]!=0)

lenans++;

}

//cout<<ans<<endl;

cout<<ans[lenans];

for (i=lenans-1;i>=1;i--)

if (ans[i]>=1000)

cout<<ans[i];

else if (ans[i]>=100)

cout<<"0"<<ans[i];

else if (ans[i]>=10)

cout<<"00"<<ans[i];

else

cout<<"000"<<ans[i];

cout<<endl;

return 0;

}

#include <stdio.h>

#include <stdlib.h>

#define maxn 100

#define maxw 100

#define div 10000

int main()

{

long n,pos,i,j,x[maxn+1],value[maxn+1][maxw+1],len[maxn+1],ans[maxw+1],lenans,s[maxw+1],lens;

scanf("%ld",&n);

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

scanf("%ld",&x[i]);

value[2][1]=1;

len[2]=1;

//高+/*低 低<除数,最多进1位

for (i=2;i<n;i++)

{

value[i+1][0]=0;

for (j=1;j<=len[i];j++)

{

value[i+1][j]=value[i][j]*i+value[i+1][j-1]/div;

value[i+1][j-1]=value[i+1][j-1]%div;

}

if (value[i+1][j-1]>=div)

{

value[i+1][j]=value[i+1][j-1]/div;

value[i+1][j-1]=value[i+1][j-1]%div;

len[i+1]=j;

}

else

len[i+1]=j-1;

}

//    for (i=2;i<n;i++)

//        value[i+1]=value[i]*i;

//不用考虑最后1位,最后一位对应的值为0

for (i=1;i<=maxw;i++)

ans[i]=0;

lenans=1;

s[0]=0;

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

{

pos=0;

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

if (x[i]>x[j])

pos++;

for (j=1;j<=len[n+1-i];j++)

{

s[j]=value[n+1-i][j]*pos+s[j-1]/div;

s[j-1]=s[j-1]%div;

}

if (s[j-1]>=div)

{

s[j]=s[j-1]/div;

s[j-1]=s[j-1]%div;

lens=j;

}

else

lens=j-1;

for (j=1;j<=lens;j++)

{

ans[j]+=s[j];

if (ans[j]>=div)

{

ans[j+1]++;

ans[j]-=div;

}

}

if (ans[lenans+1]!=0)

lenans++;

//        ans+=pos*value[n+1-i];

}

printf("%ld",ans[lenans]);

for (i=lenans-1;i>=1;i--)

if (ans[i]>=1000)

printf("%ld",ans[i]);

else if (ans[i]>=100)

printf("0%ld",ans[i]);

else if (ans[i]>=10)

printf("00%ld",ans[i]);

else

printf("000%ld",ans[i]);

printf("\n");

return 0;

}

Input:

100

100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61

60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21

20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

Output:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916863999999999999999999999999

全排序与康拓展开

n=3

全排列:

123

132

213

231

312

321

每个数列由1~n组成,且出现一次。

对于第一个位置,有n种选择,对于第二个位置,有(n-1)种选择,…,对于最后一个位置,有1种选择,所有共有n!种排序方法。

数列从小到大排序(或从大到小排序,或不排序))。

数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

而num:0~n!-1,a[k]<=k-1。

证明:

若x[n]_x[n-1]_…_x[k+1]_(min)的起始编号为x,

则x[n]_x[n-1]_…_x[k+1]_x[k]_(min)的起始编号为x+a[k]*(k-1)!,即某一个x[k]在原来的基础上加上a[k]*(k-1)!。

注意0!=1。因为定义C(x,y)=x!/(x-y)!/y!,而C(x,0)=x!/x!/0!=1,所以定义0!=1。

求全排序:

I.

dfs1,时间效率高,但数列并没有排序。

#include <iostream>

#define maxn 15

using namespace std;

//每一位的确定:还未使用的数 依次被选择(swap(a[pos],a[i]);  //以a[i]作为第pos位)

//所以数列不会产生重复

//数列没有排序!

//第pos位有1次未交换位置,(n-pos)次交换位置

//而与第pos位中的某个数延展得到的数有(n-pos)!个

//交换两数和交换回来需要6次操作

//(n-1)!*(n-1)+(n-2)!*(n-2)+…+1!*1=n!-1

//O(6*(n!-1))=O(6n!),时间复杂度很低,创建全排序效率很高!

long a[maxn+1],n;

void swap(long &a,long &b)

{

long temp;

temp=a;

a=b;

b=temp;

}

void dfs(long pos)

{

long i;

if (pos==n)

{

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

cout<<a[i]<<" ";

cout<<endl;

}

else

{

dfs(pos+1);

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

{

swap(a[pos],a[i]);  //以a[i]作为第pos位

dfs(pos+1);

swap(a[pos],a[i]);

}

}

}

int main()

{

long i;

cin>>n;

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

a[i]=i;

dfs(1);

return 0;

}

II.

dfs2,时间复杂度高

#include <iostream>

#define maxn 15

using namespace std;

//dfs:要是哪个数未被使用,就使用该数

//由于是按从小到大的顺序判断,所以数列也是从小到大排序

//dfs执行完后要改变为原来的状态(回溯):vis[i]=true;(标记该数未被使用)

//dfs时间复杂度较高

long n,a[maxn+1];

bool vis[maxn+1];

void dfs(long pos)

{

long i;

if (pos==n+1)

{

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

cout<<a[i]<<" ";

cout<<endl;

}

else

{

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

if (vis[i])

{

vis[i]=false;

a[pos]=i;

dfs(pos+1);

vis[i]=true;

}

}

}

int main()

{

long i;

cin>>n;

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

{

vis[i]=true;

a[i]=i;

}

dfs(1);

return 0;

}

III.

小到大排序,由第k个数推出第(k+1)个数

#include <stdio.h>

#include <stdlib.h>

#define maxn 15

//编号为k的数列通过一系列操作改变为编号为k+1的数列

int main()

{

long j,k,n,temp,x,y,a[maxn+1];

long long i,s;

scanf("%ld",&n);

//posibility

s=1;

for (i=2;i<=n;i++)

s=s*i;

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

a[i]=i;

for (k=1;k<=n;k++)

printf("%ld ",a[k]);

printf("\n");

for (i=1;i<s;i++)

{

//4 8 7 6 5 3 2 1

//5 8 7 6 4 3 2 1

//5 1 2 3 4 6 7 8

//从尾到头,找到第一个下降的a[j]

for (j=n-1;j>=1;j--)

if (a[j]<a[j+1])

break;

//a[j]:从尾到a[j],找到第一个比a[j]大的数a[k]

for (k=n;k>j;k--)

if (a[k]>a[j])

break;

//交换a[j]和a[k]的值

temp=a[j];

a[j]=a[k];

a[k]=temp;

//数组:j+1~n reverse

x=j+1;

y=n;

while (x<y)

{

temp=a[x];

a[x]=a[y];

a[y]=temp;

x++;

y--;

}

for (k=1;k<=n;k++)

printf("%ld ",a[k]);

printf("\n");

}

return 0;

}

IV.

康拓展开,通过数的编号逆推出数

#include <iostream>

#define maxn 15

using namespace std;

//数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

//该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

//a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

//num:0~n!-1 a[k]<=k-1

//时间复杂度:

//寻找数列:x[n]_x[n-1]_…_x[1]

//1~x[n];1~x[n-1];…;1~x[1],总x[n]+x[n-1]+…+x[1]=1+2+…+n=n*(n+1)/2

//数列共有n!个,所以O(n*(n+1)/2*n!),这是个大概值

int main()

{

long n,value[maxn+1],i,j,k,num,pos;

bool vis[maxn+1];

cin>>n;

value[1]=1;

value[2]=1;

for (i=2;i<=n;i++)

value[i+1]=value[i]*i;

for (i=0;i<value[n+1];i++)

{

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

vis[j]=false;

num=i;

for (j=n;j>=1;j--)

{

pos=num/value[j];

num-=pos*value[j];

//assume TTFTTTFFT

k=0;

while (pos>=0)

{

pos--;

k++;

while (vis[k])

k++;

}

vis[k]=true;

cout<<k<<" ";

}

cout<<endl;

}

return 0;

}

修改后速度提高:

#include <iostream>

#define maxn 15

using namespace std;

//数列:x[n]_x[n-1]_…_x[1] (从小到大排列后为1~n)

//该数列的编号:num=a[n]*(n-1)!+a[n-1]*(n-2)!+a[1]*0!

//a[k]:x[k]在当前未出现的元素中排在第(a[k]+1)个

//num:0~n!-1 a[k]<=k-1

//时间复杂度:

//寻找数列:x[n]_x[n-1]_…_x[1]

//找x[k]次需要a[k]次,寻找一个数列需要a[n]+a[n-1]+…+a[1]次操作

//a[k]:0~k-1出现概率相同,平均值为(k-1)/2

//所以a[n],a[n-1],…,a[1]的平均值为(n-1)/2,(n-2)/2,…,0

//数列共有n!个,所以O(((n-1)/2+(n-2)/2+…+0)*n!)=O((n-1)*n/4*n!)

//这个值是被低估的,但比上个方法快

int main()

{

long n,value[maxn+1],i,j,num,pos,next[maxn+1],s,head;

cin>>n;

value[1]=1;

value[2]=1;

for (i=2;i<=n;i++)

value[i+1]=value[i]*i;

for (i=0;i<value[n+1];i++)

{

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

next[j]=j+1;

head=1;

num=i;

for (j=n;j>=1;j--)

{

pos=num/value[j];

num-=pos*value[j];

//assume TTFTTTFFT

if (pos==0)

{

cout<<head<<" ";

head=next[head];

}

else

{

s=head;

while (pos>1)

{

s=next[s];

pos--;

}

cout<<next[s]<<" ";

next[s]=next[next[s]];

}

}

cout<<endl;

}

return 0;

}

康拓展开求编号

s[1],s[2],…,s[n]都不相同,且{s[1],s[2],…,s[n]}={1,2,…,n}

   X=(s[1],s[2],…,s[n])

Number(X)=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[1]*0!

a[i]:数s[i]比s[i+1]~s[n]大的个数或者s[i]-1 减去s[i]比s[1]~s[i-1]大的数目

(因为n个数从1~n且都不相同,比s[i]小的数有s[i]-1个)

如X=2413

Number(2413)=1*3!+2*2!+0*1!+0*0!=10

求一个数X的编号(从小到大排序,最小数的编号为0)

Code:

#include <stdio.h>

#include <stdlib.h>

#define maxn 15

int main()

{

long n,i,j,x[maxn+1],value[maxn+1],pos,ans=0;

scanf("%ld",&n);

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

scanf("%ld",&x[i]);

//value[1]=1;

value[2]=1;

for (i=2;i<n;i++)

value[i+1]=value[i]*i;

//不用考虑最后1位,最后一位对应的值为0

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

{

pos=0;

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

if (x[i]>x[j])

pos++;

ans+=pos*value[n+1-i];

}

printf("%ld\n",ans);

return 0;

}

Code:(高精度)

#include <iostream>

#include <memory.h>

using namespace std;

long max(long a,long b)

{

if (a>b)

return a;

else

return b;

}

int main()

{

long n,i,j,s[100],value[100][100],len[100],g,ans[100],lenans,c[100],lenc;

cin>>n;

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

cin>>s[i];

value[0][1]=0;

len[1]=1;

value[1][1]=1;

len[1]=1;

for (j=2;j<n;j++)

{

value[j][1]=0;

for (i=1;i<=len[j-1];i++)

{

value[j][i]+=value[j-1][i]*j;

if (value[j][i]>=10000)

{

value[j][i+1]=value[j][i]/10000;

value[j][i]=value[j][i]%10000;

}

else

value[j][i+1]=0;

}

if (value[j][i]==0)

len[j]=len[j-1];

else

len[j]=len[j-1]+1;

}

/*

value[0]=0;

value[1]=1;

for (i=2;i<n;i++)

value[i]=value[i-1]*i;

*/

lenans=1;

memset(ans,0,sizeof(ans));

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

{

g=0;

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

if (s[i]>s[j])

g++;

//ans+=g*value[n-i];

c[1]=0;

for (j=1;j<=len[n-i];j++)

{

c[j]+=g*value[n-i][j];

if (c[j]>=10000)

{

c[j+1]=c[j]/10000;

c[j]=c[j]%10000;

}

else

c[j+1]=0;

}

if (c[j]==0)

lenc=j-1;

else

lenc=j;

lenans=max(lenans,lenc);

for (j=1;j<=lenans;j++)

{

ans[j]+=c[j];

if (ans[j]>=10000)

{

ans[j+1]++;

ans[j]-=10000;

}

}

if (ans[j]!=0)

lenans++;

}

//cout<<ans<<endl;

cout<<ans[lenans];

for (i=lenans-1;i>=1;i--)

if (ans[i]>=1000)

cout<<ans[i];

else if (ans[i]>=100)

cout<<"0"<<ans[i];

else if (ans[i]>=10)

cout<<"00"<<ans[i];

else

cout<<"000"<<ans[i];

cout<<endl;

return 0;

}

#include <stdio.h>

#include <stdlib.h>

#define maxn 100

#define maxw 100

#define div 10000

int main()

{

long n,pos,i,j,x[maxn+1],value[maxn+1][maxw+1],len[maxn+1],ans[maxw+1],lenans,s[maxw+1],lens;

scanf("%ld",&n);

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

scanf("%ld",&x[i]);

value[2][1]=1;

len[2]=1;

//高+/*低 低<除数,最多进1位

for (i=2;i<n;i++)

{

value[i+1][0]=0;

for (j=1;j<=len[i];j++)

{

value[i+1][j]=value[i][j]*i+value[i+1][j-1]/div;

value[i+1][j-1]=value[i+1][j-1]%div;

}

if (value[i+1][j-1]>=div)

{

value[i+1][j]=value[i+1][j-1]/div;

value[i+1][j-1]=value[i+1][j-1]%div;

len[i+1]=j;

}

else

len[i+1]=j-1;

}

//    for (i=2;i<n;i++)

//        value[i+1]=value[i]*i;

//不用考虑最后1位,最后一位对应的值为0

for (i=1;i<=maxw;i++)

ans[i]=0;

lenans=1;

s[0]=0;

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

{

pos=0;

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

if (x[i]>x[j])

pos++;

for (j=1;j<=len[n+1-i];j++)

{

s[j]=value[n+1-i][j]*pos+s[j-1]/div;

s[j-1]=s[j-1]%div;

}

if (s[j-1]>=div)

{

s[j]=s[j-1]/div;

s[j-1]=s[j-1]%div;

lens=j;

}

else

lens=j-1;

for (j=1;j<=lens;j++)

{

ans[j]+=s[j];

if (ans[j]>=div)

{

ans[j+1]++;

ans[j]-=div;

}

}

if (ans[lenans+1]!=0)

lenans++;

//        ans+=pos*value[n+1-i];

}

printf("%ld",ans[lenans]);

for (i=lenans-1;i>=1;i--)

if (ans[i]>=1000)

printf("%ld",ans[i]);

else if (ans[i]>=100)

printf("0%ld",ans[i]);

else if (ans[i]>=10)

printf("00%ld",ans[i]);

else

printf("000%ld",ans[i]);

printf("\n");

return 0;

}

Input:

100

100 99 98 97 96 95 94 93 92 91 90 89 88 87 86 85 84 83 82 81 80 79 78 77 76 75 74 73 72 71 70 69 68 67 66 65 64 63 62 61

60 59 58 57 56 55 54 53 52 51 50 49 48 47 46 45 44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24 23 22 21

20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1

Output:

93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916863999999999999999999999999

时间: 2024-08-11 17:42:00

康拓排序各种求法的相关文章

全排序与康拓展开

全排列: n=3 123 132 213 231 312 321 (由1~n组成,且出现一次,从小到大排序(或从大到小排序,或不排序)) 求全排序: I. Dfs1 //全排序没有顺序 #include <iostream> using namespace std; long a[100],n; void swap(long &a,long &b) { long temp; temp=a; a=b; b=temp; } void dfs(long pos) { long i;

二叉 查找树 排序树 搜索树

二叉查找树 _ 二叉排序树 _ 二叉搜索树_C++ 一.数据结构背景+代码变量介绍 二叉查找树,又名二叉排序树,亦名二叉搜索树 它满足以下定义: 1.任意节点的子树又是一颗二叉查找树,且左子树的每个节点均小于该节点,右子树的每个节点均大于该节点. 2.由1可推出,任意节点的左孩子小于该节点,右孩子大于该节点 以上讨论的是左(右)孩子(子树)存在的情况 它的中序遍历是一个升序的排序 在参考代码中,我们定义有: 主程序中,k代表插入或删除或查找的节点的值 root,根节点位置:a[i],第 i 号节

算法总结——三大排序(快排,计数排序,归并)

快排: 适用条件:方便...只要数字不是很多 复杂度:O(nlogn)  每一层n复杂度,共logn层 原理:利用一个随机数与最后面一个数交换,那么这个随机数就到了最后一位,然后循环,如果前面的数大于最后一个数,那么把这个数放到前面去,经过一次排序之后,前面的数都是大于最后一个的,然后对1到k和k+1到n进行排序,一层一层地下去 模板: #include<cstdio> #include<algorithm> #include<time.h> using namespa

众数的求法

★问题描述:给定含有n个元素的多重集合S,每个元素在S中出现的次数称为该元素的重数.多重集S中重数最大的元素称为众数.例如,S={1,2,2,2,3,5}.多重集S的众数是2,其重数为3.★编程任务:对于给定的由n个自然数组成的多重集S,编程计算S的众数及其重数.★数据输入:输入数据由文件名为input.txt的文本文件提供.文件的第1行多重集S中元素个数n:接下来的n行中,每行有一个自然数.★结果输出:程序运行结束时,将计算结果输出到文件output.txt中.输出文件有2行,第1行给出众数,

最长上升子序列(LIS)的n*log(n)求法

方法: 对于某个序列,设一个数组,将序列第一个数放入,然后再一个一个判断序列下一位,如果大于当前数组的末尾元素,则加入数组,否则利用二分法找到第一个大于等于当前数的元素并替换,最后这个数组的长度len就是最长上升子序列的长度. 正常DP求LIS的复杂度是O(n^2),如果面对非常大量的数据的回收怎么办呢?这时候就可以用到这种求法(但是这中求法只能求出个数而不能求出正确的子序列) 这种求法实际上已经不是DP了,比较像贪心,数组代表的是"可能性",每次替换都是将"可能性"

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

数字在排序数组中出现的次数

题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 程序实现: import java.util.Scanner; public class Test38 { public static void main(String[] args) { /**  * 初始化数组,测试数据可以多种途径初始化  */   Scanner in = new Scanner(System.in); /*int[] a =