HDU 2062:Subset sequence(思維)
Subset sequence
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 8188 Accepted Submission(s): 3735
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
題意
對於一個序列,,我們稱一個非空子集元素的排列為一個子集序列。對所有的子集序列按字典順序排序。求出第m個子序列
思路
首先要求出有多少子集: 時,子集個數為1個 時,子集個數為4個 時,子集個數為15個 子集的個數滿足 以為例,將全部列出來可得: 例如: 在計算樣例3 10時,先計算第10個子集位於第幾行(以哪個數字開頭)。輸出該數字後,把該數字從中刪除,然後刪掉第二行之前的所有子集,和第二行的第一個子集,變成在剩餘集合中的子集的位置。重複操作,至到小於0為止
AC程式碼
/*
* @Author: WZY
* @School: HPU
* @Date: 2018-11-11 15:02:40
* @Last Modified by: WZY
* @Last Modified time: 2018-11-11 16:06:05
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <limits.h>
#include <map>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <string>
#include <time.h>
#define ll long long
#define ull unsigned long long
#define ms(a,b) memset(a,b,sizeof(a))
#define pi acos(-1.0)
#define INF 0x7f7f7f7f
#define lson o<<1
#define rson o<<1|1
#define bug cout<<"---------"<<endl
#define debug(...) cerr<<"["<<#__VA_ARGS__":"<<(__VA_ARGS__)<<"]"<<"\n"
const double E=exp(1);
const ll maxn=1e6+10;
const int mod=1e9+7;
using namespace std;
// F[n]=(F[n-1]+1)*n
// 計算n對應的子集的個數
ll F(ll n)
{
if(n<=1)
return n;
return (F(n-1)+1)*n;
}
int main(int argc, char const *argv[])
{
ios::sync_with_stdio(false);
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
double _begin_time = clock();
#endif
ll n,m;
ll a[30];
while(cin>>n>>m)
{
for(int i=1;i<30;i++)
a[i]=i;
int flag=0;
while(m>0)
{
ll k=F(n-1)+1; //記錄每行有多少個集合
int res=m/k+1; //記錄在第幾行
if(m%k==0) //在上一行
res--;
if(flag)
cout<<" ";
cout<<a[res];
for(int i=res;i<=n;i++)
a[i]=a[i+1];
m-=k*(res-1)+1;
n--;
flag++;
}
cout<<endl;
}
#ifndef ONLINE_JUDGE
double _end_time = clock();
printf("time = %lf ms.", _end_time - _begin_time);
#endif
return 0;
}