码迷,mamicode.com
首页 > 编程语言 > 详细

康拓排序各种求法

时间:2017-05-05 01:08:50      阅读:333      评论:0      收藏:0      [点我收藏+]

标签:long   false   bsp   ==   pac   value   center   复杂   fine   

全排序与康拓展开

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

 

康拓排序各种求法

标签:long   false   bsp   ==   pac   value   center   复杂   fine   

原文地址:http://www.cnblogs.com/cmyg/p/6810480.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!