SnackDown Longest Increasing Subsequences 构造题

Longest Increasing Subsequences

题目连接:

https://www.codechef.com/SNCKPA16/problems/MAKELIS

Description

大厨最近了解了经典的最长上升子序列问题。然而,大厨发现,虽然最长上升子序列的长度
是唯一的,但子序列本身却不一定唯一。比如,序列 [1, 3, 2, 4] 的最长上升子序列有两个:[1, 3, 4]
和 [1, 2, 4]。

大厨在这个方向上多做了些研究,然后提出了下面的这个问题:

给定 K,输出一个整数 N 以及一个 1 ∼ N 的排列,使得这一排列包含恰好 K 个最长上升子
序列。大厨要求 1 ≤ N ≤ 100,不然问题就太简单了。
如果有多种可能的答案,输出任意一种即可。

Input

输入的第一行包含一个整数 T,表示测试数据的组数。接下来是 T 组数据。

每组数据仅有一行,包含一个整数 K。

Output

对于每组数据,输出两行。第一行包含一个整数 N,第二行包含 N 个整数,即 1 ∼ N 的一个
排列,以空格分隔。

• 1 ≤ T ≤ 2 · 104
• 1 ≤ K ≤ 105

Sample Input

2
1
2

Sample Output

5
1 2 3 4 5
4
1 3 2 4

Hint

题意

题解:

很有趣的题,一般来说第一想法是分解质因数,变成乘积的形式,我不知道这样搞不搞得出来,很麻烦的样子……

这道题的正确套路是分解进制,考虑你现在是用m进制去处理这个k,你可以得到b[0]b[1]b[2]这个玩意儿,表示这个m进制的每一位是啥

你现在做出来了b0,那么你就在b[0]前面扔m个小的倒叙的,然后再后面扔一个最小的,再倒叙扔b[1]个倒叙的

这样你就得到了mb[0]+b[1]了,然后一直递归下去,你就构造出来了m进制的

经过计算,发现m=6的时候,恰好能够构造出来,所以就做出来了~

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int k;
int pri[maxn];
vector<int>p;
void init()
{
    for(int i=2;i<maxn;i++)
    {
        if(pri[i]==0)
        {
            for(int j=i+i;j<maxn;j+=i)
                pri[j]=1;
        }
    }
}
int cnt[maxn],tot=0;
int solve()
{
    scanf("%d",&k);
    if(k==1)
    {
        cout<<"1"<<endl;
        cout<<"1"<<endl;
        return 1;
    }
    if(k==2)
    {
        cout<<"2"<<endl;
        cout<<"2 1"<<endl;
        return 2;
    }
    p.clear();
    tot=0;
    while(k)
    {
        cnt[tot++]=k%6;
        k/=6;
    }
    reverse(cnt+0,cnt+tot);
    for(int i=cnt[0];i;i--)
        p.push_back(i);
    for(int i=1;i<tot;i++)
    {
        if(cnt[i]==0){
            for(int j=0;j<p.size();j++)
                p[j]+=6;
            reverse(p.begin(),p.end());
            for(int j=1;j<=6;j++)
                p.push_back(j);
            reverse(p.begin(),p.end());
            continue;
        }
 
        for(int j=0;j<p.size();j++)p[j]+=6;
        reverse(p.begin(),p.end());
        for(int j=1;j<=6;j++)
            p.push_back(j);
        reverse(p.begin(),p.end());
 
 
        for(int j=0;j<p.size();j++)p[j]+=(cnt[i]+i);
        for(int j=1;j<=i;j++)p.push_back(j);
        for(int j=cnt[i]+i;j>i;j--)
            p.push_back(j);
 
 
    }
    cout<<p.size()<<endl;
    for(int i=0;i<p.size();i++)
        cout<<p[i]<<" ";
    cout<<endl;
    return p.size();
}
int main()
{
    init();
    int t;
    scanf("%d",&t);
    while(t--)
        solve();
}
posted @ 2016-06-05 22:58  qscqesze  阅读(350)  评论(0编辑  收藏  举报