【康拓逆展开】HDU2062Subset sequence

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2062

Problem Description

Consider the aggregate An= { 1, 2, …, n }. For example, A1={1}, A3={1,2,3}. A subset sequence is defined as a array of a non-empty subset. Sort all the subset sequece of An in lexicography order. Your task is to find the m-th one.

Input

The input contains several test cases. Each test case consists of two numbers n and m ( 0< n<= 20, 0< m<= the total number of the subset sequence of An ).

Output

For each test case, you should output the m-th subset sequence of An in one line.

Sample Input

1 1
2 1
2 2
2 3
2 4
3 10

Sample Output

1
1
1 2
2
2 1
2 3 1

可以用vector实现康拓逆展开;

代码:

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<vector>
#define LL long long
using namespace std;
int ans[30];
int len=0;
LL fac[23];
/*      康拓逆展开已AC
void Cantor(int n,LL m)
{
    int N=n;
    int i,j,vis[23]={0};
    while(n--&&m){
        LL t=m/fac[n+1];
        if(m%fac[n+1]) t+=1;
        LL k=t;
        for(i=1;i<=N;i++){
            if(!vis[i]){
                k--;
                if(k==0) break;

            }
        }
        vis[i]=1;
        ans[len++]=i;
        m-=((t-1)*fac[n+1]+1);
    }
}
*/
//  用vector实现康拓逆展开
void Cantor(int n,LL m)
{
    vector<int>q;
    for(int i=1;i<=20;i++){
        q.push_back(i);
    }
    while(n--&&m){
        LL t=m/fac[n+1];
        if(m%fac[n+1]) t+=1;
        ans[len++]=q[t-1];
        q.erase(q.begin()+t-1);
        m-=((t-1)*fac[n+1]+1);
    }
}
void f()
{
    fac[0]=0;
    fac[1]=1;       //  注意数据类型;
    for(int i=2;i<=21;i++){
        fac[i]=fac[i-1]*(i-1)+1;
    }
}
int main()
{
    f();
    LL n,m;
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    cin.sync_with_stdio(false);
    while(cin>>n>>m){
        len=0;
        Cantor(n,m);
        for(int i=0;i<len;i++){
            if(i<len-1) cout<<ans[i]<<' ';
            else cout<<ans[i]<<endl;
        }
    }
    return 0;
}
时间: 2024-08-02 09:15:02

【康拓逆展开】HDU2062Subset sequence的相关文章

HDU 1027 Ignatius and the Princess II(康托逆展开)

Ignatius and the Princess II Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4865    Accepted Submission(s): 2929 Problem Description Now our hero finds the door to the BEelzebub feng5166. He o

康托展开和逆展开

康托展开: 给定一个排列(由n个数排列而成),我们可以计算出该排列在由n个数组成的所有排列中排名第几(按字典序),这就是康托展开. 比如由4个数1,2,3,4组成排列 那么2413在所有的排列中排第几呢? 首先计算第一位数字比2小的排列有多少种,即 1 * fac[3],怎么得来的呢?首先比2小的数字只有1个,那么第一位数字只有一种选择,剩下的三位数字有fac[3]种选择,所以是1 * fac[3] 现在当第一位固定是2,那么来计算第二位数字比4小的排列有多少种呢?首先比4小的数字有1个,那么第

康托逆展开

刚才学弟问,不好意思说不知道康托逆展开是个什么东西= =.然后硬着头皮百度了一下,找到了思路,顺手就敲了一下,发上来吧: 求n个数的第m大的全排列. 思路链接: 戳这里... 代码贴出来 :简单的写下注释..0.0 1 #include <iostream> 2 using namespace std; 3 const int MAXN = 13; 4 int num[MAXN]; 5 int jie[12]={1, 1, 2, 6, 24, 120, 720, 5040, 40320, 36

康托展开、康托逆展开原理

康托展开 康托展开的公式是 X=an*(n-1)!+an-1*(n-2)!+...+ai*(i-1)!+...+a2*1!+a1*0! 其中,ai为当前未出现的元素中是排在第几个(从0开始). 这个公式可能看着让人头大,最好举个例子来说明一下.例如,有一个数组 s = ["A", "B", "C", "D"],它的一个排列 s1 = ["D", "B", "A", &

康托(逆)展开(2015.8.6)

康托展开 X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0! 其中,a[i]为整数,并且X=a[n]*(n-1)!+a[n-1]*(n-2)!+...+a[i]*(i-1)!+...+a[1]*0!.这就是康托展开.康托展开可用代码实现. ——百度百科 这个东西,我们高三的时候称作OhYee第一定理(还有第二第三).当时做排列组合做到疯的时候推出来的.然而我们数学老师觉得没什么琴里用→_→ 对于八数码问题,在储存时有一个问题,就是八数码

【全排列】HDU1027Ignatius and the Princess II/HDU1716排列2

全排列函数,666,上次蓝桥杯就沾了全排列的光.... next_pernutation(); 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1716 Problem Description Ray又对数字的列产生了兴趣: 现有四张卡片,用这四张卡片能排列出很多不同的4位数,要求按从小到大的顺序输出这些4位数. Input 每组数据占一行,代表四张卡片上的数字(0<=数字<=9),如果四张卡片都是0,则输入结束. Output 对每组卡片按从小到

hihoCoder #1312 : 搜索三&#183;启发式搜索(A*, 康托展开)

原题网址:http://hihocoder.com/problemset/problem/1312 时间限制:10000ms 单点时限:1000ms 内存限制:256MB   描述 在小Ho的手机上有一款叫做八数码的游戏,小Ho在坐车或者等人的时候经常使用这个游戏来打发时间. 游戏的棋盘被分割成3x3的区域,上面放着标记有1~8八个数字的方形棋子,剩下一个区域为空. 游戏过程中,小Ho只能移动棋子到相邻的空区域上.当小Ho将8个棋子都移动到如下图所示的位置时,游戏就结束了. 小Hi:小Ho,你觉

康托展开-全排列应用

我排第几个 时间限制:1000 ms  |  内存限制:65535 KB 难度:3 描述 现在有"abcdefghijkl"12个字符,将其所有的排列中按字典序排列,给出任意一种排列,说出这个排列在所有的排列中是第几小的? 输入 第一行有一个整数n(0<n<=10000);随后有n行,每行是一个排列: 输出 输出一个整数m,占一行,m表示排列是第几位: 样例输入 3 abcdefghijkl hgebkflacdji gfkedhjblcia 样例输出 1 30271524

hdu 1043 Eight(康托展开,打表)

1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef long long LL; 5 6 /** 7 学习:(1)康托展开的使用 8 (2)路径记录 9 ? A* 10 ? 双向bfs 11 */ 12 13 int t[9],s[9]; 14 bool vis[362880 + 10]; 15 char ans[362880 + 10][42]; 16 int fac[]={1,1