1. 程式人生 > >模擬 nbut1225 NEW RDSP MODE I

模擬 nbut1225 NEW RDSP MODE I

研究 tar 復雜 function pac efi 找規律 ref 時間

傳送門:點擊打開鏈接

題意:輸入n。m,x。剛開始有一個1~n的排列。然後定義了一種操作。是將數組中的偶數位數字選出來,依照順序放到數組最前面,奇數位依照順序放到偶數位的後面,進行m次這種操作。輸出之後前x個數字

思路:找到循環節T,利用T去約m,然後再將非常小的m拿去模擬,輸出前x個

一開始就想到找循環節,,剛開始僅僅想到去用找規律的方法去找到通項公式,可是找了好久就是沒找到。盡管感覺理論上肯定是有的T^T

可是找規律的時候發現了非常多特點:T一定小於等於n。還有就是最剛開始的時候數字1是在第一個位置。當數字1再次出如今第一個位置的時候,剛好就是一個循環節!

所以。我們僅僅須要模擬1的位置,一直模擬到1出如今第一個位置時,循環節就算出來了。復雜度O(n)。1的位置還是非常好模擬的,由於僅僅研究了一個數字而已,還是非常好找到遞推式子的。

找到循環節T之後。我們令m=m%T.這樣m就變成<=n的了。然後就能夠再次模擬

接下來,我們對前x個數字,分別倒著模擬m次。由於如今的m<=n,所以復雜度O(xn),倒著模擬的公式也是非常好找的


最後看別人的代碼才發現,,事實上模擬的時候。就是一個高速冪(fuck)

總之。還是有些感慨。有時候不一定模擬就非要找到通項公式。找到辦法能在較短的時間內算出通項公式,這樣也並不算差~

#include<map>
#include<set>
#include<cmath>
#include<stack>
#include<queue>
#include<cstdio>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<functional>
#define FIN freopen("input.txt","r",stdin)
#define FOUT freopen("output.txt","w+",stdout)

using namespace std;
typedef long long LL;
typedef pair<int, int> PII;

const int MX = 1e5 + 5;
const int INF = 0x3f3f3f3f;

int find_t(int n) {
    int p = 1, ret = 0;
    while(true) {
        ret++;
        if(p % 2) p = n / 2 + (p + 1) / 2;
        else p = p / 2;

        if(p == 1) return ret;
    }
}
int solve(int p, int n, int m) {
    for(int i = 1; i <= m; i++) {
        if(p * 2 <= n) p = p * 2;
        else p = (p - n / 2 - 1) * 2 + 1;
    }
    return p;
}

int main() {
    int n, m, x;//FIN;
    while(~scanf("%d%d%d", &n, &m, &x)) {
        int t = find_t(n);

        for(int i = 1; i <= x; i++) {
            printf("%d%c", solve(i, n, m % t), i == x ?

'\n' : ' '); } } return 0; }



模擬 nbut1225 NEW RDSP MODE I