Stratoes:首先假设k ≤ n – 1,那么我们可以这么做:将每个牌中间留一个空位,每次把牌堆顶的第一张牌放到合适的空位上,可以证明这么做是可行的。因此我们维护一个数组和一个指向牌堆顶的指针,一开始将第i张牌放在2*i-1的位置。第j次操作时将牌堆顶的牌放在(j + 1) * 2的位置即可。这样我们就在O(n)时间内完成了要求的操作。
当k很大时,假设n-1次后的编号为p[i],则2(n – 1)次后的编号为p[p[i]], 以此类推。令x = ⌊k / n⌋,则我们通过将排列p的拆分成若干个循环,就可以通过循环节的长度求得p^x,即k – k % (n – 1)次后的编号,剩下k % (n – 1)次直接模拟就好。总的时间复杂度为O(n)。

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e6 + 10;
typedef long long ll;
int n;
ll k;
int p[maxn], tmp[maxn];
bool vis[maxn];
void getNext(int * a, int k)
{
    memset(tmp, 0, sizeof tmp);
    for(int i = 1; i <= n; ++i) tmp[(i << 1) - 1] = a[i];
    int cur = 1;
    for(int i = 1; i <= k; ++i)
    {
        while(!tmp[cur]) ++cur;
        swap(tmp[cur], tmp[(i + 1) << 1]);
    }
    int tot = 0;
    for(int i = 1; i <= 2 * n; ++i)
        if(tmp[i])
            a[++tot] = tmp[i];
}
void getCycle(int * a, ll k)
{
    for(int i = 1; i <= n; ++i)
        if(!vis[i])
        {
            int cur = i, tot = 0;
            while(!vis[cur])
            {
                tmp[++tot] = cur;
                vis[cur] = 1;
                cur = a[cur];
            }
            tmp[0] = tmp[tot];
            int shift = k % tot;
            for(int j = 0; j < tot; ++j)
                a[tmp[j]] = tmp[(j + shift) % tot];
        }   
}
int main()
{
    cin >> n >> k;
    for(int i = 1; i <= n; ++i) p[i] = i; 
    getNext(p, n - 1);
    getCycle(p, k / (n - 1));
    getNext(p, k % (n - 1));
    for(int i = 1; i <= n; ++i) cout << p[i] << ' ';
    cout << '\n';
    return 0;
}

Dzerzhinski: k – k % (n – 1)部分也可以快速幂计算。整体复杂度是O(n log(k/n))

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int arr[1001000];
int temp[2002000];
int powans[1001000];
int n;
ll k;
void step(int pre[],int step){
    for(int i=0;i<n;i++){
        temp[i*2]=pre[i];
        temp[i*2+1]=0;
    }
    int now = 0;
    for(int i=0;i<step;i++){
        while(temp[now]==0)now++;
        swap(temp[now],temp[(i+1)*2+1]);
    }
    now=0;
    for(int i=0;i<2*n;i++){
        if(temp[i])pre[now++]=temp[i];
    }
}
void mul(int a[],int b[]){
    for(int i=0;i<n;i++){
        temp[i]=a[b[i]-1];
    }
    for(int i=0;i<n;i++)a[i]=temp[i];

}

void powmod(int a[],ll p){
    for(int i=0;i<n;i++)powans[i]=i+1;
    while(p){
        if(p%2){
            mul(powans,a);
        }
        p/=2;
        mul(a,a);
    }
}

int main(){
    cin>>n>>k;
    for(int i=0;i<n;i++)arr[i]=i+1;
    step(arr,n-1);
    powmod(arr,k/(n-1));
    step(powans,k%(n-1));

    for(int i=0;i<n;i++){
         cout<<powans[i]<<" ";
    }
    cout<<endl;
    return 0;
}