• 无聊的序列 


    题面

    【问题描述】

    ​ MrKill上了高数之后超无聊,觉得好像很简单的样子。

    ​ 一天老师看他很不爽,下课约到了办公室(很抱歉现实中大学咩有老师会约你)。一张无限长的纸上,写了n个数,分别是1到n。老师觉得好像他全懂了,指着这张纸:“你知道GCD吗?我今天上课才讲的。”

    “这还不简单???”

    “那把这些n个数的GCD写下来”

    老师随机删了一个数又这么问,反复了n-1次之后,只有一个数了,老师推了推眼镜,把这个数填在了你写的

    序列的末尾。MrKill获得了传说道具——LS序列。

    老师重新抽了一张无限长的纸写了n个数,分别是1到n。老师把笔给了你,让你也来动手删一删,然后写下

    字典序最大的LS序列就让你放学。MrKill手足无措,满头大汗,他还想着马上赶去聚会呢。

    ​ 救救孩子。

    【输入格式】

    ​ 输入文件名为 sequence.in。

    ​ 输入多个数表示n(小数据不超过50个、大数据不超过1个)读到0结束。

    【输出格式】

    输入文件名为 sequence.out。

    ​ 输出数据为多串长度为n的序列,代表字典序最大的LS序列

    【输入输出样例1】

    sequence.in sequence.out
    3 1 1 3
    2 1 2
    1 1
    0

    样例1解释:

    对于序列1、2、3

    ① 一个数没有删的时候(GCD(1,2,3)= 1)

    ② MrKill选择把2先删了发现没有什么用(GCD(1,3)= 1)

    ③ MrKill发现删了1可以变大(GCD(3)= 3)

    他不知道怎么回事就做对了

    【数据规模与约定】 (这道题我真的不知道怎么送分)

    对于20%的数据(n ≤ 10)

    对于60%的数据 (n ≤ 1000)

    对于 100%的数据 (n ≤ 5*10^6)

    题解

    一道偏简单的性质构造题

    我们考虑这样一个事实(GCD ( a,a+1)= 1),为了让字典序最大,我们需要尽快把相邻的两项清掉,但是删去

    奇数还是偶数呢?当然是删奇数,因为偶数有共同的(GCD=2),奇数却不一定有共同的(GCD)。这样我们就保

    证了最快使得非1元素出现,贪心使得字典序最大。

    接下来怎么办呢?

    我们把剩下的数除以2,再做一遍刚才一样的操作,利用一个计数器,记录除了多少个二或者直接记录(2^k) 这样,

    一步一步除下来,就可以得到最终序列了。

    然而这样处理到最后,需要判断(n=1,2,3)的情况,留给你们自己思考(考场上应该就做出来的)。

    可能还有一些小朋友没理解,可以去和别人讨论讨论,这是一种相当典型的第一题用去奇数再除以2的序列递

    归。除了序列递归,还有很多种可以利用除以2来解决的事情,可以考虑考虑再出一道题坑别人,防止被坑。

    p.s:我们并不是直接对序列进行除以2的操作,而是知道了序列长度,我就能够通过除以2来知道当前GCD应

    该要删掉多少个数之后才能变大,而变大之前,这个数是定值。

    后话

    样例其实很良心了,把需要特殊处理的1,2,3的情况都给出来了

    (n=2)的情况,可以显然得出前一个数和后一个成1:2的关系

    (n=3)的情况,例如(2,4,6)这个例子,我们先删除2,再删除4,然后删除6,可以显然得出是字典序最大的方案

    也就是(2,2,6)(now,now,now*3)

    那么我们每次把数列缩小到二分之一,递归处理,注意特判(n=1,n=2,n=3)的情况即可

    代码

    #include <bits/stdc++.h>
    using namespace std;
    void solve(int n, int now) {
        if (!n) {
            puts("");
            return;
        }
        if (n == 1) {
            printf("%d
    ", now);
            return;
        }
        if (n == 2) {
            printf("%d %d
    ", now, now * 2);
            return;
        }
        if (n == 3) {
            printf("%d %d %d
    ", now, now, 3 * now);
            return;
        }
        for (int i = 1; i <= (n + 1) / 2; i++) printf("%d ", now);
        solve(n >> 1, now * 2);
    }
    int main() {
        while (1) {
            int n;
            scanf("%d", &n);
            if (!n)
                break;
            solve(n, 1);
        }
        return 0;
    }
    
  • 相关阅读:
    【DWM1000】 code 解密2一 工程初始化代码分析
    【DWM1000】 code 解密1一 去掉Main 函数多余内容
    Integration between SharePoint 2013 and CRM 2013 (On-Premise)
    Windows Server2012R2 添加Microsoft .NET Framework 3.5 功能失败的解决方法
    Windows Server2012R2 安装 SharePoint 2013 的必备组件
    SSRS: How to Display Checkbox on Report
    ADFS部署过程中设置network service对证书的读取权限
    Dynamics CRM2013 ScLib::AccessCheckEx failed
    ADFS3.0 Customizing the AD FS Sign-in Pages
    Dynamics CRM2013 picklist下拉项行数控制
  • 原文地址:https://www.cnblogs.com/bangdexuanyuan/p/14000129.html
Copyright © 2020-2023  润新知