码迷,mamicode.com
首页 > 其他好文 > 详细

第17届科大讯飞杯 I-纸牌 (循环节 思维)

时间:2020-05-12 11:22:22      阅读:86      评论:0      收藏:0      [点我收藏+]

标签:out   sizeof   假设   wap   scan   acm   unsigned   can   ace   

题目:传送门

题意

技术图片

 

 思路

对于 k <= n - 1 的情况,我们可以将全部的牌隔一个位存起来,也就是起初的时候,第 i 张牌,放在 b[ 2 * i - 1 ] 的位置。每次操作将第 i 张牌放到第 (i - 1) % (n - 1) + 2 = i + 1 的位置的下一位,即放到 b[ 2 * (i + 1) ] 的位置。因为在 i 之前的操作,都不会将牌放到 2 * (i + 1) 之后,所以,第 i 次操作,可以保证在 2 * (i + 1) 前恰好有 i 张牌,所以这么做是可行的。

对于 k > n - 1的情况,假设 n - 1 次操作后的编号为 a[ i ],则 2(n - 1) 次操作后的位置为 a[ a[ i ] ],以此类推,那我们可以对数组 a 找出所有的环,令 Z = k / (n - 1),即这个环需要转 Z 步,令 cnt 为环的长度,那么转了 cnt 步就等于没转,所以只需转 Z % cnt 步即可。剩下的 k % (n - 1) 直接按 k <= n - 1 做一次就好了。

 

#include <bits/stdc++.h>
#define LL long long
#define ULL unsigned long long
#define UI unsigned int
#define mem(i, j) memset(i, j, sizeof(i))
#define rep(i, j, k) for(int i = j; i <= k; i++)
#define dep(i, j, k) for(int i = k; i >= j; i--)
#define pb push_back
#define make make_pair
#define INF 0x3f3f3f3f
#define inf LLONG_MAX
#define PI acos(-1)
#define fir first
#define sec second
#define lb(x) ((x) & (-(x)))
#define dbg(x) cout<<#x<<" = "<<x<<endl;
using namespace std;

const int N = 1e6 + 5;

int a[N], b[N << 1];

bool vis[N];

void getnx(int n, int k) {

    rep(i, 1, n) {

        b[2 * i] = 0;

        b[2 * i - 1] = a[i];

    }

    int now = 1;

    rep(i, 1, k) {

        while(!b[now]) now++;

        swap(b[now], b[(i + 1) * 2]);

    }

    now = 0;

    rep(i, 1, 2 * n) {

        if(b[i]) a[++now] = b[i];

    }

}

void getloop(int n, LL k) { /// 找循环

    rep(i, 1, n) {

        if(vis[i]) continue;

        int cnt = 0, now = i;

        while(!vis[now]) { /// 找循环长度

            vis[now] = 1;

            b[++cnt] = now;

            now = a[now];

        }

        int need = k % cnt;

        b[0] = b[cnt];

        rep(i, 1, cnt) { /// 环转动 need 步

            a[b[i]] = b[(i + need) % cnt];

        }

    }

}

void solve() {

    int n;

    LL k;

    scanf("%d", &n);

    scanf("%lld", &k);

    rep(i, 1, n) a[i] = i;

    getnx(n, n - 1);

    getloop(n, k / (n - 1));

    getnx(n, k % (n - 1));

    rep(i, 1, n) printf("%d ", a[i]);

}

int main() {

//    int _; scanf("%d", &_);
//    while(_--) solve();

    solve();

    return 0;
}

 

第17届科大讯飞杯 I-纸牌 (循环节 思维)

标签:out   sizeof   假设   wap   scan   acm   unsigned   can   ace   

原文地址:https://www.cnblogs.com/Willems/p/12874876.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!