作者: 赵晓鹏时间限制: 1S章节: 递归与分治

 
#include <iostream>
#include <algorithm>
#include <queue>
#include <tuple>
#include <stack>
#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3,"Ofast","inline")
using namespace std;
const int LENGTH=(1<<22)+3;
int A[LENGTH]={1,1};
int pos=0;
const int groupLen=25;
const int h=160;
int recordPass=0;
inline int Partition(int left, int right, int x)
{
    A[pos]=A[left];
    int i = left, j = right+1;
    while(true)
    {
        while(i < j && A[--j] >= x);
        while(i < j && A[++i] < x);
        if(i>=j) break;
        swap(A[i], A[j]);
    }
    A[left]=A[i];
    A[i]=x;
    return i;
}
int select(int first, int last, int r)
{
    if(last - first < h)
    {
        priority_queue<int>Q(A + first, A + last + 1);
        for(int i=last; i>=first; --i)
        {
            A[i]=Q.top();
            Q.pop();
        }
        return A[r + first - 1];
    }
    pos=first+rand()%(last-first);
    int x = A[pos];
    int mid= Partition(first, last, x);
    int res = mid - first + 1;
    int locLeft=mid;
    int locRight=last+1;
    int m=0;
    if(r < res) return select(first, mid, r);
    else
    {
        while(true)
        {
            while(A[++locLeft]==x&&locLeft<locRight);
            while((A[--locRight]^x)&&locLeft<locRight);
            if(locLeft>=locRight)
            {
                m=locLeft-mid-1;
                break;
            }
            A[locRight]=A[locLeft];
            A[locLeft]=x;
        }
        if(m>=1&&r>=res&&r<=m+res-1) return x;
        else return select(mid + 1+m, last, r - res-m);
    }
}
void res(int left, int right, int leftNum, int rightNum, int k) {
    int B[rightNum+1];
    stack<tuple<int, int, int, int>> stk;
    stk.push(make_tuple(left, right, leftNum, rightNum));
    while (!stk.empty()) {
        int left, right, leftNum, rightNum;
        tie(left, right, leftNum, rightNum) = stk.top();
        stk.pop();
        if (leftNum > rightNum) {
            continue;
        }
        int mid = (leftNum + rightNum) >> 1;
        int midPos = (mid + 1) <<k;
        select(left, right, midPos - left + 1);
        B[mid]=A[midPos-1];
        stk.push(make_tuple(midPos + 1, right, mid + 1, rightNum));
        stk.push(make_tuple(left, midPos, leftNum, mid - 1));
    }
    for(int i=leftNum;i<=rightNum;++i){
        if(i==rightNum){
            printf("%d",B[i]);
        }
        else{
            printf("%d ",B[i]);
        }
    }
}
int main()
{
    int n,k,m;
    scanf("%d%d%d", &n,&k,&m);
    int  len=1<<n;
    for(int  i=2; i<len; ++i)
    {
        A[i]=(A[i-1]+A[i-2])%m;
    }
    int unit=1<<k;
    int maxNum=len/unit;
    res(0, len-1, 0,maxNum-1, k);
    return 0;
}


















