zoukankan      html  css  js  c++  java
  • JZOJ3403[NOIP2013模拟]数列变换(2019.08.04[NOIP提高组]模拟 B 组T1)

    传送门

    数列变换 (Standard IO)

    Time Limits: 1000 ms  Memory Limits: 524288 KB  Detailed Limits  

    Time to Submit: 01:59:36

    Description

    小X 看到堆成山的数列作业十分头疼,希望聪明的你来帮帮他。考虑数列A=[A1,A2,...,An],定义变换f(A,k)=[A2,A3,,,,.Ak,A1,Ak+2,Ak+3,,,,A2k,Ak+1,...],也就是把a 分段,每段k 个(最后如果不足k 个,全部分到新的一段里,见样例),然后将每段的第一个移动到该段的最后一个。

    现在,小 X想知道 f (f (f (f ([1,2,3,⋯,n],2),3),⋯),n)的结果。

    Input

    输入一行包含一个整数n 。

    Output

    输出一行包含n 个整数,表示最终的数列。

    Sample Input

    4

    Sample Output

    4 2 3 1

    【样例说明】

    f ([1,2,3,4],2) = [2,1,4,3]

    f ([2,1,4,3],3) = [1,4,2,3](3单独被分在一组,移动到组的最后一位,仍然是3)

    f ([1,4,2,3],4) = [4,2,3,1]

    Data Constraint

    对于60%的数据,1≤ n ≤10^3。

    对于100%的数据,1≤ n ≤10^6。

    分析题意

    在考场上分析这道题题意耗了半天时间。简单来说,是对数列{1,2,3...,n-1,n}进行n次操作,每次进行分段,第i次操作每段有i个数(末尾的自成一段),将每段的第一个数放到末尾。

    这道题实际就是模拟,难点在于如何进行操作。

    一、六十分暴力

    根据题意直接暴力即可。

     

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1e6 + 7;
    int n;
    int num[MAXN];
    void test()
    {
        for(register int i = 1; i <= n; ++i)
        {
            cerr<<num[i]<<' ';
        }
        cerr<<endl;
    }
    inline void change(int x)
    {
        register int tmp = num[1];
        for(register int i = 1; i <= n - n % x; ++i)
        {
            if( i % x == 0)
            {
                num[i] = tmp;
                tmp = num[i+1];
            }
            else
            {
                num[i] = num[i+1];
            }
        }
        if(n % x != 0)
        {
            tmp = num[n - n % x + 1];
            for(register int i = n - n % x + 1; i <= n - 1; ++i)
            {
                num[i] = num[i + 1];
            }
            num[n] = tmp;
        }
    }
    int main()
    {
    #ifdef lky233
        freopen("testdata.in","r",stdin);
        freopen("testdata_5.out","w",stdout);
    #endif
        int tim = clock();
        n = 100000;
        for(register int i = 1; i <= n; ++i)
            num[i] = i;
        for(register int i = 1; i <= n; ++i)
        {
            change(i);
    #ifdef lky233
        if(i % 1000 == 0)
            cerr<<i<<endl;
        if(i % 10000 == 0)
            cerr<<"C"<<i,cerr<<"using time "<<clock() - tim<<"ms."<<endl;
    #endif
        }
        printf("0,");
        for(register int i = 1; i <= n; ++i)
            printf("%d,",num[i]);
    #ifdef lky233
        cerr<<"using time "<<clock() - tim<<"ms."<<endl;
    #endif
    }

     

    本来考场上用这个打表来着,但是空间不够。

    后来打算把1e5,1e6这个肯定会有的数据打过去,然而1e6跑了半个小时才跑了一半(纪中的垃圾机子),后来去了一趟wc机子跪了。。。

    提交的时候发现1e5的数据太多提示CE。

    果然投机取巧会被制裁。

    二、八十分做法

    这里使用memcpy极大缩短数组复制所需时间,可以卡常拿到80分。

    三、正确做法

    我们会发现之前的暴力有很多无用的操作,就是将这一段并未进行操作的数copy到前面。那么我们可以考虑将进行操作的数后移,时间复杂度为O(nlogn)。

    比如{1,2,3,4,5,6} --> {0,2,1,4,3,6,5},这个1放到原先3的位置,3放到原先5的位置,以此类推。

    在实际运算时,用一个head数记录当前数列开头在数组的哪个位置,其余正常操作。

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 2e6 + 7;
    int num[MAXN];
    int n;
    int head;
    void test()
    {
    #ifdef lky233
        for(register int i = 1; i <= head + n; ++i)
            cerr<<num[i];
        cerr<<endl;
    #endif
    }
    void move(int x)
    {
        int tmp_1 = num[head],tmp_2;
        for(register int i = head + x ; i <= n + head - 1;i+=x)
        {
            tmp_2 = num[i];
            num[i] = tmp_1;
            tmp_1 = tmp_2;
            test();
        }
        num[n + head] = tmp_1;
    }
    int main()
    {
        cin>>n;
        for(register int i = 1; i <= n; ++i)
            num[i] = i;
        for(register int i = 2; i <= n; ++i)
        {
            ++head;
            move(i);
            test();
        }    
        ++head;
        for(register int i = head; i <= head + n - 1; ++i)    
            cout<<num[i]<<' ';
    }

    OK这道模拟就用一点技巧过了。

     

  • 相关阅读:
    linux下利用valgrind工具进行内存泄露检测和性能分析
    Linux下内存泄漏工具
    linux下将不同线程绑定到不同core和cpu上——pthread_setaffinity_np
    Linux下getopt()函数
    SparkStreaming+Kafka整合
    Hive+Sqoop+Mysql整合
    crontab
    Hive与Hbase整合
    关系数据库数据与hadoop数据进行转换的工具
    Flume+Kafka+Storm+Hbase+HDSF+Poi整合
  • 原文地址:https://www.cnblogs.com/Shiina-Rikka/p/11299714.html
Copyright © 2011-2022 走看看