zoukankan      html  css  js  c++  java
  • hdu多校第五场1005 (hdu6628) permutation 1 排列/康托展开/暴力

    题意:

    定义一个排列的差分为后一项减前一项之差构成的数列,求对于n个数的排列,差分的字典序第k小的那个,n<=20,k<=1e4。

    题解:

    暴力打表找一遍规律,会发现,对于n个数的排列,如果想找到差分的字典序第k小的,如果k<=(n-1)!,那么对应的那个排列就是把第一位赋值为n,后面的是1~n-1的元素本身排列字典序第k小的。

    比如,4个元素的排列的差分字典序最小的前6个分别是

    4,1,2,3

    4,1,3,2

    4,2,1,3

    4,2,3,1

    4,3,1,2

    4,3,2,1

    当n为10或更多的时候,(n-1)!>1e4,便可用康托逆展开直接计算。

    当n为9以下时,原先的想法是在本地暴力排序,对于每个n都取前1e4个元素交表。后来发现hdu限制提交代码大小,分析了一下,9!约等于3e5,暴力打表,过了。

    #include<iostream>
    #include<vector>
    #include<algorithm>
    #define LL long long
    using namespace std; 
    int MAXN;
    LL fact[25];
    int tmp[30];
    struct Node{
        int px[12];//排列
        int cha[12];//排列的差分
        int indexpx;
        int indexcha;
        friend bool operator > (const Node &a,const Node &b){
            for(int i=1;i<MAXN;i++){
                if(a.cha[i]!=b.cha[i])return a.cha[i]>b.cha[i];
            }
        }
        friend bool operator < (const Node &a,const Node &b){
            for(int i=1;i<MAXN;i++){
                if(a.cha[i]!=b.cha[i])return a.cha[i]<b.cha[i];
            }
        }
        //比较差分的字典序
    }node[10000000];
    int ans[10][100005];
    void make_ans(){
        for(int i=1;i<=MAXN;i++){
            node[1].px[i]=i;
            node[1].cha[i-1]=1;
        }
        node[1].indexpx=1;
        int i,n;
        for(i=2;;i++){
            for(int j=1;j<=MAXN;j++){
                node[i].px[j]=node[i-1].px[j];
            }
            if(!next_permutation(&node[i].px[1],&node[i].px[MAXN+1])){
                n=i-1;
                break;
            }
            
            for(int j=1;j<MAXN;j++){
                node[i].cha[j]=node[i].px[j+1]-node[i].px[j];
            }
            
            node[i].indexpx=i;
        }
        sort(node+1,node+1+n);
        for(int i=1;i<=min(n,10000);i++){
            ans[MAXN][i]=node[i].indexpx;
        }
        //暴力打表预处理
    }
    void make_fact(){
        fact[0]=1;
        for(int i=1;i<=20;i++){
            fact[i]=fact[i-1]*i;
        }
    }
    void Cantor_invexp(int *p,int len,LL rank){
        //康托逆展开
        int temp[len];
        for(int i=0;i<len;i++){
            temp[i]=i+1;
        }
        for(int i=1;i<=len;i++){
            int a=rank/fact[len-i];
            rank%=fact[len-i];
            for(int j=0;j<len;j++){
                if(a==0 && temp[j]>0){
                    p[i]=temp[j];
                    temp[j]=0;
                    break;
                }else if(temp[j]>0){
                    a--;
                }
            }
        }
        return ;
    }
    
    int main(){
        make_fact();
        for(int i=2;i<=9;i++){
            MAXN=i;
            make_ans();
        }
        
    //    return 0;
        int t;
        scanf("%d",&t);
        while(t--){
            int n,k;
            scanf("%d %d",&n,&k);
            if(n>=10){
                printf("%d",n);
                Cantor_invexp(tmp,n-1,1LL*k-1);
                for(int i=1;i<=n-1;i++){
                    printf(" %d",tmp[i]);
                }
                printf("
    ");
            }else{
                Cantor_invexp(tmp,n,1LL*ans[n][k]-1);
                for(int i=1;i<=n;i++){
                    printf("%d",tmp[i]);
                    if(i<n)printf(" ");
                    else printf("
    ");
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    看板娘相关源码介绍
    Spring框架实体bean转json返回前端报错:Null key for a Map not allowed in JSON (use a converting NullKeySerializer?)
    Spring Data JPA介绍以及dao层(持久层)标准接口或自定义方法规则
    BeanNotOfRequiredTypeException:Bean named 'XXXX' is expected to be of type 'XXX' but was actually of type 'com.sun.proxy.$Proxy211'
    RedisDesktopManager的编译
    Spring-Boot中@Scheduled注解不生效
    @Async 注解不生效
    使用MongoTemplate,启动时候报错:org.springframework.beans.factory.BeanCreationException
    【个人经验之谈】计算机相关的就业、培训等问题解疑答惑
    简单java mail demo收发邮件例子,各种邮件类型
  • 原文地址:https://www.cnblogs.com/isakovsky/p/11305964.html
Copyright © 2011-2022 走看看